2010-05-02 21 views
11

Possiedo un'applicazione Web ASP.NET MVC che implementa un provider di appartenenze personalizzato. Il provider di appartenenza personalizzato prende uno UserRepository nel suo costruttore che fornisce un'interfaccia tra il provider di appartenenza e NHibernate. Il UserRepository viene fornito dal contenitore IoC Ninject.Iniezione di dipendenza con provider di appartenenze personalizzate

Ovviamente, tuttavia, questo non funziona quando il provider è istanziato da .NET: il costruttore senza parametri non ha un repository utente e non può crearne uno (il repository utente richiede una sessione di NHibernate passata al suo costruttore), che quindi significa che il fornitore non può accedere al suo archivio dati. Come posso risolvere la dipendenza dell'oggetto?

Probabilmente vale la pena notare che questa è un'applicazione esistente che è stata aggiornata con Ninject. Precedentemente ho usato costruttori senza parametri che erano in grado di creare le loro dipendenze richieste insieme ai costruttori parametrici per assistere il collaudo delle unità.

Qualche idea, o mi sono costruito in un angolo qui?

risposta

5

Si potrebbe voler mantenere il costruttore senza parametri, che inizializza i repository necessari utilizzando Ninject. Potresti voler usare lo Common Service Locator, quindi non avrai bisogno di avere né un riferimento a Ninject né un contenitore nel tuo provider personalizzato. Sembra che Ninject non abbia un'implementazione ufficiale dell'adattatore per CSL, ma scrivere uno non dovrebbe essere troppo difficile (controllare le altre implementazioni, come quella di Windsor), e sono sicuro che ci sia un'implementazione non ufficiale da qualche parte.

+3

Ninject ha avuto un adattatore CSL ufficiale gennaio 2010. –

+0

Manca ancora dalla home page di CSL (è invece incluso nella versione di NInject) – SztupY

+1

"costruttore, che inizializza i repository necessari utilizzando Ninject" - attenzione, se i repository (o le loro dipendenze) sono in ambito di richiesta o transitorio e qualsiasi il contesto di dati usa e getta entra in gioco, finirai per accedere a un contesto di dati disponibili su tutti tranne la prima richiesta (perché non controlli la durata del provider e ASP.NET lo riutilizzerà tra le richieste). Ho finito per ottenere un'istanza di repository dal localizzatore ogni volta che dovevo chiamarne uno quando mi sono imbattuto in questo problema. –

-1

Ho avuto lo stesso problema, l'ho risolto passando i dati richiesti utilizzando il ticket di autenticazione all'oggetto di identità.

Quindi nessun oggetto deve essere iniettato nei provider di appartenenza.

Nel mio codice di autenticazione ho

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

E in 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); 
      } 
     } 
    } 

E in classe Identità devo proprietà MemberName, nome e cognome che restituiscono parti di corda biglietto.

+0

prega potrebbe andare in un po 'più in dettaglio? Come sarebbe, ad esempio, la funzione di override di CreateUser() nel tuo scenario? Stai dicendo che nel mio scenario dovrei passare l'oggetto repository nel ticket di autenticazione? – alastairs

+0

Invece di passare il repository, passare l'id utente –

+0

cosa ?? Sono d'accordo con @alastairs, come crei utenti e altre cose senza un repository? – mare

4

Poiché la raccolta dei membri e l'istanza MemberShip.Provider vengono create prima che Ninject possa istanziarle, è necessario eseguire l'attivazione della creazione post sull'oggetto. Se contrassegni le tue dipendenze con [Inject] per le proprietà nella classe del tuo provider, puoi chiamare kernel.Inject (MemberShip.Provider) - questo assegnerà tutte le dipendenze alle tue proprietà.

risposta
+0

Suona bene; L'ho risolto con il CSL, ma potrebbe valere la pena di rivedere per rimuovere la dipendenza extra. – alastairs

+0

+1 Mi piace questo metodo. – Pandincus

+2

Dove chiameresti kernel.Inject ...? – Matt

Problemi correlati