2010-05-02 1 views
11

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

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

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

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

ответ

5

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

+3

Ninject имеет официальный адаптер CSL Январь 2010. –

+0

Он по-прежнему отсутствует на домашней странице CSL (вместо этого он включен в версию NInject) – SztupY

+1

«конструктор, который инициализирует необходимые репозитории с помощью Ninject» - смотрите, если ваши репозитории (или их зависимости) находятся в области «Запрос» или «Переход» и любые вид контекста одноразовых данных вступает в игру, в конечном итоге вы получите доступ к контексту данных с информацией обо всех, кроме первого запроса (поскольку вы не контролируете время жизни Поставщика, а ASP.NET будет повторно использовать его в запросах). Я закончил с получением экземпляра репозитория от локатора каждый раз, когда мне нужно было позвонить ему, когда я столкнулся с этой проблемой. –

-1

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

Тогда никакие объекты не должны вводиться в поставщиков членства.

В моем коде проверки подлинности У меня есть

[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); 
      } 
     } 
    } 

И в классе идентичности у меня есть MemberName, ПгвЬЫат и LastName свойство, которые возвращают части строки билета.

+0

Пожалуйста, не могли бы вы пойти в немного более подробно? Как, например, функция переопределения CreateUser() в вашем сценарии? Вы говорите, что в моем сценарии мне пришлось бы передать объект репозитория в билет аутентификации? – alastairs

+0

Вместо передачи репозитория передать идентификатор пользователя –

+0

что ?? Я согласен с @alastairs, как вы создаете пользователей и другие вещи без репозитория? – mare

4

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

+0

Звучит неплохо; Я решил это с помощью CSL, но, возможно, стоит повторно посетить, чтобы удалить дополнительную зависимость. – alastairs

+0

+1 Мне нравится этот метод. – Pandincus

+2

Где бы вы могли назвать kernel.Inject ...? – Matt

4

Правильный ответ от Michael B. из: Dependency injection and ASP.Net Membership Providers

Вы можете получить свой репозиторий (или услугу) инъекции таким образом:

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