开发者

Injecting Repository In MembershipProvider.Initialize()? Bad Idea?

I am building an asp.net MVC2 web app using StructureMap. I have created a custom MembershipProvider. I get it properly initialized at startup by calling:

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

In Initialize(), I am thinking of instantiating a repository to use for access to User data in the database.

So, I put in a private property in my custom MembershipProvider:

private IUserRepository userRepository;

And, inside Initialize(), I call:

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

First, is it "good practice" to instantiate a repository in my custom MembershipProvider?

Second, when I implement it, it seems like I can't access any StructureMap configuration that was properly setup in global.asax. When I call Debug.WriteLine(ObjectFactory.WhatDoIHave()) just before the above GetInstance() line, none of the configuration data is present (which I do see from the same Debug line placed in global.asax) and I get a "No Default Instance defined for PluginFamily CPOP.Domain.Contract开发者_JAVA百科s.Repositories.IUserRepository" error when calling GetInstance(). Why is that? Seems like I have a whole different container inside MembershipProvider.


Ended up using setter injection in StructureMap. The userRepository property in the custom MembershipProvider can be configured by calling:

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>(); });
    ...
}); 

And, then calling BuildUp() on a target instance. I do this in Application_Start(), after all the registries have been called and StructureMap has all the configuration data.

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

Done.


Thank you very much for answering your question...it was exactly what I was looking for.

Modified slightly for me, the trick was configuring everything via ObjectFactory (just as above) and using that ObjectFactory's container for 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));

This way, everything works from a Controller factory standpoint, and the MembershipProvider is "built up" after the fact (since it's already been constructed before Application_Start thanks to .NET.) This code above is called from Application_Start.


The membership provider is basically singleton which means only single instance will be created by ASP.NET. So don't keep anything in private fields/properties unless you want some surprises in production when two threads are using the same membership provider same time.

I only needed to implement ValidateUser since we don't use any other methods and I did it like this:

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

Of course you need to configure the DependencyResolver, StructureMap etc. but the point is that the ISession is not kept in private field/property.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜