自定义会员资格提供程序中的 Unity 依赖项注入

发布于 2024-11-17 22:38:41 字数 1078 浏览 4 评论 0原文

我有 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; }

例如,在控制器中工作得很好。

有谁知道为什么会这样以及该怎么办?

I have ASP.NET MVC3 project where I want to use custom membership provider. Also I want to use Unity for resolving my dependency injection.

this is code from 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));

    }

this is code from my membership provider:

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

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

Problem is when I put breakpoint to ValidateUser method I see that Repository property not initialized. But this construction:

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

for example, works fine in controllers.

Does anybody know why it is so and what to do?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

说好的呢 2024-11-24 22:38:41

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

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

I had the same problem over the last couple of days. I ended up with the following solution (type and field names changed to match yours).

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

So even though Unity is not in control of the building of the CustomMembershipProvider, the parameterless constructor gets Unity involed (via the MVC3 DependencyResolver) to supply the correct repository instance.

If you're unit testing the CustomMembershipProvider then you can just build an instance with Unity directly, which will use the second constructor and avoid the call to DependencyResolver.

巷雨优美回忆 2024-11-24 22:38:41

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

  • 您没有将其配置为这样做
  • CustomMembershipProvider 未由 Unity 解析,因此它无法控制向其中注入依赖项

如果您在代码中使用会员资格 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。

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

Unity cannot inject IProveaRepository instance into you custom membership provider because :

  • You did not configured it to do so
  • CustomMembershipProvider is not resolved by unity so it has no control on injecting into it the dependencies

If you're using your membership priovider class in your code you could do the following :

Try to wrapp your customMembershipProvider in an abstraction for example IMembershipProvider that has only signature for methods that you use. The result is like that :

public class CustomMembershipProvider : MembershipProvider, IMembershipProvider

Then you could register it in unity :

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

Then the constraint is to pass the dependency in your controller like that :

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

But it would be event better to not user the property injection but the constructor injection like that :

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

   public CustomMembershipProvider(IProveaRepository proveaRepository)
   {
     Repository = proveaRepository
   }

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

It's the way I understand it and would do it. But maybe there is a better approach or I'm ignoring some of Unity API that would help to achieve it easier.

Anyway I hope it helps.

凉风有信 2024-11-24 22:38:41

正如其他人所说,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)
   {
       .....
   }

我希望它有所帮助。

While as others said Unity cannot inject dependencies in providers because they're not known
to the container and, even if could be a registration of a provider, you haven't a "factory point" where building the provider through the container, there's a solution which doesn't violate good design principles. (This because, even if most people ignore this, using a ServiceFactory is too close to an antipattern...)

But, a good solution could be the association of using the [Dependency] attribute in conjunction with the Unity BuildUp method.

So taking your example, to get what you're trying to do, leave all the things as they are, and put in the provider constructor the BuildUp call

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

I hope it helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文