依赖注入和ASP.Net会员提供程序

34

我正在创建一个自定义的成员身份提供程序,并将其作为一个较大库的一部分创建为一个单独的类,该网站是基于ASP.Net MVC的。由于后端数据存储可以是Xml文件或SQL数据库,因此需要灵活处理。我的初始想法是为数据存储创建一个接口,并使用依赖注入将其注入到提供程序中。

最终需要的结果是开发人员可以继承数据存储接口并提供所需的方法来更新数据,然后可由自定义成员身份提供程序使用。

但是由于我个人技能不足,我无法弄清楚如何在将其添加到网站时将类注入到成员身份提供程序中。与提供程序链接数据存储需要做什么?最简单的方法是什么,以实现在网站中启用此功能?


你熟悉任何依赖注入框架吗? - Restuta
@Restuta - 不,我不是在寻找一个框架。对于这个特定的需求,一个简单的接口就足够了。开发人员应该能够通过继承接口来创建自己的后端存储。 - BinaryMisfit
1
我认为框架可以节省很多时间。它将用于向您的自定义成员资格提供程序注入特定实现,这项任务最为复杂,因为您无法控制提供程序初始化。 - Restuta
@Restuta - 公正的评论,但不是我要找的。第一名是使用我上面想到的方法来完成它。我更喜欢不依赖于提供比我需要的更多的外部框架。 - BinaryMisfit
3个回答

33
如果您正在通过Web.config文件中的元素配置自定义成员资格提供程序,那么我可以看到您在依赖注入方面可能遇到的问题。
这些提供程序是由框架构建和管理的,您没有机会拦截该构造函数以为接口提供附加的依赖注入。
如果我的假设是正确的,那么您可以在自定义提供程序中覆盖Initialize()方法,并在那里进行依赖注入。您可以在提供程序配置中具有自定义名称/值设置,该设置指向实现IDataStore接口的类型,并将其作为字典的一部分传递给Initialize()方法。
然后,您激活数据存储类型的一个实例并将其设置在适当的属性上:
public class MyMembershipProvider : MembershipProvider
{
    public IDataStore DataStore
    {
        get;
        set;
    }

    public override Initialize(string name, NameValueCollection config)
    {
        var dataStoreType = config["dataStoreProvider"];
        if (!String.IsNullOrEmpty(dataStoreType))
        {
            var type = Type.GetType(dataStoreType);
            DataStore = (IDataStore) Activator.CreateInstance(type);
        }
    }
}

Initialize()方法将在框架构造提供程序实例后被调用,因此这是执行任何其他设置工作的完美场所。

对于测试场景,您只需在提供程序实例本身上设置数据存储属性,因为您将直接在测试中构造它。


这里有一个类似的修复方法:http://bugsquash.blogspot.com.au/2010/11/windsor-managed-membershipproviders.html。它基本上实现了装饰者设计模式,以包装由DI容器创建的实例。 - Mark Whitfeld

20

这不是更好吗?我在MVC3和ninject中使用它。只需向自定义成员资格提供程序类添加属性即可。记得在顶部添加"using System.Web.Mvc;"。

public IRepository Repository
{
    get
    {
        return DependencyResolver.Current.GetService<IRepository>();
    }
}

可能吧。我已经有一段时间没有看过这个了,而且当时提出问题的时候还是MVC 1.0版本。 - BinaryMisfit
1
它对我有效。缺点是它是“服务定位器”反模式的变体,但有时您必须做出架构妥协。(请参见https://dev59.com/BWEh5IYBdhLWcg3wHARD。)我不知道他们是否应该在ASP.NET vNext中修复此问题,但希望如此。 - Ken Smith

2

在我看来,最简单的依赖注入方式(实际上也是我迄今为止使用过的唯一一种方式...)是让您的依赖类的构造函数接受接口作为参数,并将其分配给私有字段。如果需要,您还可以添加一个“默认”构造函数,它会使用默认值链到第一个构造函数中。

简化后,代码如下:

public class DependentClass
{
    private IDataStore _store;

    // Use this constructor when you want strict control of the implementation
    public DependentClass(IDataStore store)
    {
         this._store = store;
    }

    // Use this constructor when you don't want to create an IDataStore instance
    // manually every time you create a DependentClass instance
    public DependentClass() : this(new DefaultDataStore()) { }
}

这个概念被称为“构造函数链”,网络上有很多关于如何实现它的文章。我发现这篇教程非常详细地解释了DI模式。


谢谢。我经常使用DI,所以我对这部分相当熟悉。我的问题特定于在web.config中配置的成员资格提供程序。Sam的解决方案解决了这个问题。 - BinaryMisfit
@Sleeper:他说他正在使用ASP.NET MVC,这意味着可以通过容器解析类。我建议他应该这样做。顺便说一下,你不必大声喊叫。 - Tomas Aschan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接