2010-05-02 16 views
11

J'ai une application Web ASP.NET MVC qui implémente un fournisseur d'appartenances personnalisé. Le fournisseur d'appartenance personnalisée prend un UserRepository à son constructeur qui fournit une interface entre le fournisseur d'appartenances et NHibernate. Le UserRepository est fourni par le conteneur Ninject IoC. Cependant, cela ne fonctionne pas lorsque le fournisseur est instancié par .NET: le constructeur sans paramètre n'a pas de UserRepository et ne peut pas en créer un (le UserRepository nécessite qu'une session NHibernate soit passée à son constructeur), qui alors signifie que le fournisseur ne peut pas accéder à son magasin de données. Comment puis-je résoudre ma dépendance aux objets?Injection de dépendances avec fournisseur d'appartenances personnalisées

Il est probablement intéressant de noter que c'est une application existante qui a été modernisés avec Ninject. Auparavant, j'utilisais des constructeurs sans paramètres qui étaient capables de créer leurs dépendances requises en conjonction avec les constructeurs paramétrés pour faciliter les tests unitaires.

Des pensées, ou est-ce que je me suis construit dans un coin ici?

Répondre

5

Vous pouvez conserver le constructeur sans paramètre, qui initialise les référentiels nécessaires à l'aide de Ninject. Vous voudrez peut-être utiliser le Common Service Locator, vous n'aurez donc pas besoin de faire référence à Ninject ni à son conteneur dans votre fournisseur personnalisé. Il semble que Ninject n'a pas d'implémentation d'adaptateur officielle pour CSL, mais écrire ne devrait pas être dur (vérifier les autres implémentations, comme celles de Windsor), et je suis sûr qu'il y a une implémentation non officielle quelque part.

+3

Ninject a eu un adaptateur CSL officiel Janvier 2010. –

+0

Il manque toujours de la page d'accueil CSL (il est inclus dans la version NInject à la place) – SztupY

+1

"constructeur, qui initialise les référentiels nécessaires en utilisant Ninject" - attention, si vos référentiels (ou leurs dépendances) sont dans la portée Request ou Transient et le type de contexte de données jetable entre en jeu, vous finirez par accéder à un contexte de données éliminées sur toutes sauf la première requête (car vous ne contrôlez pas la durée de vie d'un fournisseur et ASP.NET le réutilisera à travers les requêtes). J'ai fini par obtenir une instance de référentiel du localisateur à chaque fois que je devais en appeler un quand je rencontrais ce problème. –

-1

J'ai eu le même problème, je l'ai résolu en transmettant les données requises en utilisant un ticket d'authentification à l'objet d'identité.

Aucun objet ne doit ensuite être injecté dans les fournisseurs d'appartenances.

Dans mon code d'authentification je

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

Et dans 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); 
      } 
     } 
    } 

Et dans la classe Identity je MemberName, les propriétés Nom et prénom qui renvoient les parties de la chaîne de billets.

+0

S'il vous plaît pourriez-vous aller dans un peu plus de détails? Comment, par exemple, la fonction de substitution CreateUser() dans votre scénario? Voulez-vous dire que dans mon scénario, je devrais passer l'objet du référentiel dans le ticket d'authentification? – alastairs

+0

Au lieu de passer l'ID de l'utilisateur du référentiel –

+0

what ?? Je suis d'accord avec @alastairs, comment créer des utilisateurs et d'autres choses sans référentiel? – mare

4

Depuis la collection des membres et l'instance MemberShip.Provider sont créés avant Ninject l'instancier, vous devez effectuer l'activation après la création de l'objet. Si vous marquez vos dépendances avec [Inject] pour vos propriétés dans la classe de votre fournisseur, vous pouvez appeler kernel.Inject (MemberShip.Provider) - ceci assignera toutes les dépendances à vos propriétés.

+0

Ça sonne bien; Je l'ai résolu avec le CSL, mais il pourrait être utile de re-visiter pour enlever la dépendance supplémentaire. – alastairs

+0

+1 J'aime cette méthode. – Pandincus

+2

Où appelleriez-vous kernel.Inject ...? – Matt