【问题标题】:Dependency injection and ASP.Net Membership Providers依赖注入和 ASP.Net Membership Providers
【发布时间】:2010-12-05 19:24:33
【问题描述】:

我正在为 ASP.Net MVC 网站创建自定义成员资格提供程序。提供程序被创建为一个单独的类,作为更大库的一部分。后端数据存储需要灵活,因为它可以是 Xml 文件或 SQL 数据库。我最初的想法是为数据存储创建一个接口,并使用依赖注入将其注入提供程序。

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

但是由于我自己缺乏技能,在将课程添加到网站时,我无法弄清楚如何将课程注入会员提供者?需要做什么才能将数据存储链接到提供者?在网站中启用此功能的最简单方法是什么?

【问题讨论】:

  • 你熟悉任何依赖注入框架吗?
  • @Restuta - 不,我不是在寻找框架。一个简单的界面就足以满足这一特定要求。开发者应该能够通过简单地继承接口来创建自己的后端商店。
  • 我认为框架可以为您节省大量时间。它将用于将特定实现注入到您的自定义 Membership 提供程序中,此任务最复杂,因为您无法控制提供程序初始化。
  • @Restuta - 公平的评论,但不是我想要的。一等奖是使用我上面想到的方法进行的。我不想依赖于提供比我需要的更多的外部框架。

标签: asp.net-mvc dependency-injection membership-provider data-storage


【解决方案1】:

我见过的最简单的依赖注入方法(实际上是我迄今为止唯一使用过的方法......)是让依赖类的构造函数将接口作为参数,并分配它到私人领域。如果需要,您还可以添加一个“默认”构造函数,该构造函数链接到第一个具有默认值的构造函数。

简化,看起来像这样:

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()) { }
}

这个概念被称为“构造函数链”,网上有很多关于如何做到这一点的文章。我发现this tutorial 对 DI 模式非常有解释性。

【讨论】:

  • 谢谢。我经常使用 DI,所以我对这部分很满意。我的问题特定于在 web.config 中配置的成员资格提供程序。 Sam 的解决方案解决了这个问题。
  • @Sleeper:他说他正在使用 ASP.NET MVC,这意味着可以通过容器解析类。我建议他应该这样做。顺便说一句,你不必尖叫。
【解决方案2】:

如果您通过 Web.config 文件中的 元素配置自定义成员资格提供程序,那么我可以看到您在依赖注入时会遇到的问题。

提供程序由框架构建和管理,您没有机会拦截该构建以为IDataStore 接口提供额外的依赖注入。

如果我的假设是正确的,那么您可以做的是覆盖自定义提供程序中的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() 将在框架构造您的提供程序的实例后被框架调用,因此这是进行任何额外设置工作的理想场所。

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

【讨论】:

【解决方案3】:

这不是更好吗?我将它与 MVC3 和 ninject 一起使用。将属性添加到您的自定义成员资格提供程序类就足够了。记得添加“使用 System.Web.Mvc;”在上面。

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

【讨论】:

  • 可能。我有一段时间没看这个了,在问这个问题的时候它仍然是 MVC 1.0
  • 它对我有用。缺点是它是“服务定位器”反模式的变体,但有时您必须在架构上做出妥协。 (见stackoverflow.com/questions/22795459/…)我不知道他们是否应该在 ASP.NET vNext 中解决这个问题,但希望如此。
猜你喜欢
  • 2010-10-27
  • 2015-10-20
  • 2011-03-18
  • 1970-01-01
  • 1970-01-01
  • 2014-07-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多