【问题标题】:Unity dependency injection in custom membership provider自定义成员资格提供程序中的 Unity 依赖注入
【发布时间】:2011-06-29 10:01:36
【问题描述】:

我有 ASP.NET MVC3 项目,我想在其中使用自定义成员资格提供程序。我也想使用 Unity 来解决我的依赖注入。

这是来自 Global.asax 的代码:

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterGlobalFilters(GlobalFilters.Filters);
        RegisterRoutes(RouteTable.Routes);

        var container = new UnityContainer();
        container.RegisterType<IAuthentification, Authentification>();
        container.RegisterType<IRepository, Repository>();

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

    }

这是来自我的会员提供商的代码:

public class CustomMembershipProvider : MembershipProvider
{
   [Dependency]
   private IProveaRepository Repository { get; set; }

   public override bool ValidateUser(string username, string password)
    {
       .....
    }

问题是当我将断点设置为 ValidateUser 方法时,我看到 Repository 属性未初始化。但是这个结构:

   [Dependency]
   private IProveaRepository Repository { get; set; }

例如,在控制器中可以正常工作。

有人知道为什么会这样以及该怎么做吗?

【问题讨论】:

    标签: asp.net-mvc-3 dependency-injection unity-container membership


    【解决方案1】:

    过去几天我遇到了同样的问题。我最终得到了以下解决方案(类型和字段名称已更改为与您的匹配)。

    public class CustomMembershipProvider : MembershipProvider       
    {
        private IProveaRepository repository;
    
        public CustomMembershipProvider() 
            : this (DependencyResolver.Current.GetService<IProveaRepository>())
        { }
    
        public CustomMembershipProvider(IProveaRepository repository)
        {
            this.repository= repository;
        }
    
        public override bool ValidateUser(string username, string password)
        {
            ...
        }
    }
    

    因此,即使 Unity 无法控制 CustomMembershipProvider 的构建,无参数构造函数也会调用 Unity(通过 MVC3 DependencyResolver)以提供正确的存储库实例。

    如果您正在对CustomMembershipProvider 进行单元测试,那么您可以直接使用 Unity 构建一个实例,它将使用第二个构造函数并避免调用 DependencyResolver

    【讨论】:

      【解决方案2】:

      Unity 无法将 IProveaRepository 实例注入您的自定义成员资格提供程序,因为:

      • 您没有将其配置为这样做
      • CustomMembershipProvider 没有被统一解决,因此它无法控制向其中注入依赖项

      如果您在代码中使用会员 priovider 类,您可以执行以下操作:

      尝试将您的 customMembershipProvider 包装在一个抽象中,例如 IMembershipProvider,它只有您使用的方法的签名。结果是这样的:

      public class CustomMembershipProvider : MembershipProvider, IMembershipProvider
      

      那你就可以统一注册了:

      container.RegisterType<IMembershipProvider, CustomMembershipProvider>(new InjectionProperty(new ResolvedParameter<IProveaRepository>()));
      

      那么约束就是像这样在你的控制器中传递依赖:

      public class HomeController : Controller
      {
       private IMembershipProvider _membershipprovider;
       public HomeController(IMembershipProvider membershipProvider)
       {
         _membershipProvider = membershipProvider
       }
       // some actions
      }
      

      但最好不要使用属性注入,而是使用构造函数注入:

      public class CustomMembershipProvider : MembershipProvider
      {
         private IProveaRepository Repository { get; set; }
      
         public CustomMembershipProvider(IProveaRepository proveaRepository)
         {
           Repository = proveaRepository
         }
      
         public override bool ValidateUser(string username, string password)
          {
             .....
          }
      

      这是我理解并愿意这样做的方式。但也许有更好的方法,或者我忽略了一些有助于更轻松实现它的 Unity API。

      无论如何,我希望它有所帮助。

      【讨论】:

      • 我实现了类似于@Thomas Jaskula 的最后一个代码示例的东西,我的依赖项被注入到自定义提供程序的构造函数中。但是,当我尝试创建 MembershipUser 的新实例时(例如,在实现 GetUser 时),会引发 TargetInvocationException,抱怨我的自定义提供程序没有无参数构造函数。有关如何解决此问题的任何想法?
      【解决方案3】:

      正如其他人所说,Unity 无法在提供程序中注入依赖项,因为它们是未知的 到容器,即使可能是提供者的注册,你也没有通过容器构建提供者的“工厂点”,有一个不违反良好设计原则的解决方案。 (这是因为,即使大多数人忽略了这一点,使用 ServiceFactory 也太接近反模式了......)

      但是,一个好的解决方案可能是将 [Dependency] 属性与 Unity BuildUp 方法结合使用。

      以你的例子为例,为了得到你想要做的事情,让所有的东西保持原样,然后在提供者构造函数中放入 BuildUp 调用

      public class CustomMembershipProvider : MembershipProvider
      {
         [Dependency]
         private IProveaRepository Repository { get; set; }
      
         public CustomMembershipProvider()
         {
           //contextual obtained container reference 
           unityContainer.BuildUp(this);
           .....
         }
         public override bool ValidateUser(string username, string password)
         {
             .....
         }
      

      希望对你有帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        相关资源
        最近更新 更多