2010-08-17 12 views
1

Je construis une application Web asp.net MVC2 en utilisant StructureMap. J'ai créé un MembershipProvider personnalisé. Je reçois correctement initialisé au démarrage en appelant:Injection de référentiel dans MembershipProvider.Initialize()? Mauvaise idée?

x.For<MembershipProvider>().Use(Membership.Provider); 
x.For<IMembershipProvider>().Use<CPOPMembershipProvider>(); 

En initialize(), je pense à l'instanciation d'un référentiel à utiliser pour l'accès aux données de l'utilisateur dans la base de données.

Alors, je mets dans une propriété privée dans mon MembershipProvider personnalisé:

private IUserRepository userRepository; 

Et, à l'intérieur initialize(), je l'appelle:

IUserRepository userRepository = ObjectFactory.GetInstance<IUserRepository>(); 

D'abord, est-il "bonnes pratiques" à instancier un référentiel dans mon MembershipProvider personnalisé?

En second lieu, quand je mets en œuvre, il semble que je ne peux pas accéder à toutes les configurations de StructureMap qui a été configuré dans le global.asax. Quand j'appelle Debug.WriteLine (ObjectFactory.WhatDoIHave()) juste avant la ligne, aucune des données de configuration est présent (que je ne vois de la même ligne de débogage placé dans global.asax) GetInstance ci-dessus() et je reçois un " Aucune instance par défaut définie pour l'erreur PluginFamily CPOP.Domain.Contracts.Repositories.IUserRepository "lors de l'appel de GetInstance(). Pourquoi donc? On dirait que j'ai un conteneur différent dans MembershipProvider.

Répondre

3

a fini par utiliser setter injection dans StructureMap. La propriété userRepository dans le MembershipProvider personnalisé peut être configuré en appelant:

CPOPMembershipProvider member = 
    (CPOPMembershipProvider) Membership.Providers["CPOPMembershipProvider"]; 
ObjectFactory.Configure(x => 
{ 
    ... 
    x.For<MembershipProvider>().Use(Membership.Provider); 
    x.For<IMembershipProvider>().TheDefault.Is.Object(member); 
    ... 
    x.For<IPatientRepository>().Use<PatientRepository>(); 
    x.For<IUserRepository>().Use<UserRepository>(); 
    x.SetAllProperties(y => { y.OfType<IUserRepository>(); }); 
    ... 
}); 

Et puis appeler BuildUp() sur une instance cible. Je le fais dans Application_Start(), après que tous les registres ont été appelés et StructureMap a toutes les données de configuration.

ObjectFactory.BuildUp(Membership.Providers["CPOPMembershipProvider"]); 

Terminé.

+0

Exactement ce dont j'avais besoin. –

0

Merci beaucoup pour répondre à votre question ... c'était exactement ce que je cherchais.

légèrement modifiée pour moi, le tour était tout configure via ObjectFactory (comme ci-dessus) et en utilisant le conteneur de ObjectFactory pour DependencyResolver:

UserMembershipProvider provider = 
(UserMembershipProvider)Membership.Providers["UserMembershipProvider"]; 

ObjectFactory.Configure(x => 
{ 
    x.For<ISessionFactory>() 
     .Singleton() 
     .Use(() => NHibernateInitializer.Initialize().BuildSessionFactory()); 
    x.For<IEntityDuplicateChecker>().Use<EntityDuplicateChecker>(); 
    x.For(typeof(IRepository<>)).Use(typeof(Repository<>)); 
    x.For(typeof(IRepositoryWithTypedId<,>)).Use(typeof(RepositoryWithTypedId<,>)); 
    x.SetAllProperties(y => 
    { 
     y.WithAnyTypeFromNamespaceContainingType<IEntityDuplicateChecker>(); 
    }); 
}); 

ObjectFactory.BuildUp(provider); 
DependencyResolver.SetResolver(
    new StructureMapDependencyResolver(ObjectFactory.Container)); 

De cette façon, tout fonctionne à partir d'un point de vue de l'usine de contrôleur, et le MembershipProvider est "construit" après le fait (puisqu'il a déjà été construit avant Application_Start grâce à .NET.) Ce code ci-dessus est appelé depuis Application_Start.

0

Le fournisseur d'appartenances est essentiellement singleton ce qui signifie que seule instance sera créé par ASP.NET. Donc, ne gardez rien dans les champs/propriétés privés à moins que vous ne vouliez des surprises dans la production lorsque deux threads utilisent le même fournisseur d'appartenances en même temps.

Je ne devais mettre en œuvre ValidateUser puisque nous ne pas utiliser d'autres méthodes et je l'ai fait comme ceci:

public bool ValidateUser(string userName, string password) 
{ 
    var session = DependencyResolver.Curret.GetService<ISession>(); 

    using (session) 
    { 
     using (var tx = session.BeginTransaction()) 
     { 
      // load the user from db and validate the password etc. 
      tx.Commit(); 
     } 
    } 
} 

Bien sûr, vous devez configurer le DependencyResolver, StructureMap etc., mais le point est que l'ISession n'est pas conservée dans un domaine privé/propriété.