Внедрение зависимостей Unity в настраиваемый поставщик членства - PullRequest
5 голосов
/ 29 июня 2011

У меня есть проект 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, я вижу, что свойство репозитория не инициализировано.Но эта конструкция:

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

, например, прекрасно работает в контроллерах.

Кто-нибудь знает, почему это так и что делать?

Ответы [ 3 ]

17 голосов
/ 22 марта 2012

У меня была та же проблема за последние пару дней. В итоге я нашел следующее решение (имена типов и полей изменены в соответствии с вашими). ​​

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.

1 голос
/ 29 июня 2011

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, которые могли бы помочь в его достижении.

В любом случае, я надеюсь, что это поможет.

0 голосов
/ 24 сентября 2013

В то время как другие говорили, что 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)
   {
       .....
   }

Надеюсь, это поможет.

...