Инъекция зависимостей с пользовательским поставщиком членства

У меня есть веб-приложение ASP.NET MVC, которое реализует пользовательский поставщик членства. Пользовательский поставщик членства принимает UserRepository в свой конструктор, который обеспечивает интерфейс между поставщиком членства и NHibernate. UserRepository предоставляется контейнером Ninject IoC.

Очевидно, однако, это не работает, когда поставщик создается .NET: конструктор без параметров не имеет UserRepository и не может его создать (UserRepository требует, чтобы сеанс NHibernate передавался его конструктору), что затем означает что поставщик не может получить доступ к своему хранилищу данных. Как я могу разрешить свою зависимость от объекта?

Возможно, стоит отметить, что это существующее приложение, которое было доработано с помощью Ninject. Раньше я использовал беззазорные конструкторы, которые могли создавать свои необходимые зависимости в сочетании с параметризованными конструкторами для поддержки модульного тестирования.

Любые мысли, или я закрепил себя в углу здесь?

Ответ 1

Возможно, вы захотите сохранить конструктор без параметров, который инициализирует необходимые репозитории, используя Ninject. Возможно, вы захотите использовать Common Service Locator, поэтому вам не нужно иметь ни ссылки на Ninject, ни контейнера внутри вашего настраиваемого поставщика. Кажется, что Ninject не имеет официальной реализации адаптера для CSL, но писать не следует, чтобы сложно (проверьте другие реализации, например Windsor), и я уверен, что там где-то неофициальная реализация.

Ответ 2

Так как коллекция членства и экземпляр MemberShip.Provider создаются до того, как Ninject может их создать, вам необходимо выполнить активацию после создания объекта. Если вы помечаете свои зависимости с помощью [Inject] для своих свойств в вашем классе поставщика, вы можете вызвать kernel.Inject(MemberShip.Provider) - это назначит все зависимости вашим свойствам.

Ответ 4

У меня была такая же проблема, я решил ее, передав необходимые данные с использованием аутентификационного билета в объект идентификации.

Затем никакие объекты не должны вводиться в провайдеры членства.

В моем коде аутентификации у меня есть

    [NonAction]
    private void SetAuthTicket(Member member, bool isPersistent)
    {
        HttpCookie cookie = Request.Cookies.Get(FormsAuthentication.FormsCookieName);

        FormsAuthentication.SetAuthCookie(member.Email, isPersistent);

        string userData = "|" + member.ID + "|" + member.Firstname + "|" + member.Lastname + member.Culture;

        FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(1, member.Email, DateTime.UtcNow, DateTime.UtcNow.AddDays(7), isPersistent, userData);

        string encryptedTicket = FormsAuthentication.Encrypt(ticket);
        cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
        Response.Cookies.Add(cookie);
    }

И в Global.asax

    void Application_OnPostAuthenticateRequest(object sender, EventArgs e)
    {
        IPrincipal user = HttpContext.Current.User;
        if (user.Identity.IsAuthenticated && user.Identity.AuthenticationType == "Forms")
        {
            FormsIdentity identity = user.Identity as FormsIdentity;

            MyIdentity ai = new MyIdentity(identity.Ticket);            
            MyPrincipal p = new MyPrincipal(ai);

            HttpContext.Current.User = p;
            System.Threading.Thread.CurrentPrincipal = p;

            if (!String.IsNullOrEmpty(ai.Culture))
            {
                CultureInfo ci = new CultureInfo(ai.Culture);
                System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
                System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
            }
        }
    }

И в классе Identity у меня есть свойства MemberName, Firstname и Lastname, которые возвращают части строки билета.