在MembershipProvider.Initialize()中注入存储库?馊主意?

时间:2010-08-17 00:06:53

标签: asp.net-mvc-2 structuremap membership-provider

我正在使用StructureMap构建一个asp.net MVC2 Web应用程序。我创建了一个自定义MembershipProvider。我通过调用:

在启动时正确初始化它
x.For<MembershipProvider>().Use(Membership.Provider);
x.For<IMembershipProvider>().Use<CPOPMembershipProvider>();

在Initialize()中,我正在考虑实例化一个存储库,用于访问数据库中的用户数据。

所以,我在自定义MembershipProvider中输入了一个私有属性:

private IUserRepository userRepository;

而且,在Initialize()中,我打电话给:

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

首先,在我的自定义MembershipProvider中实例化存储库是“良好做法”吗?

其次,当我实现它时,似乎我无法访问在global.asax中正确设置的任何StructureMap配置。当我在上面的GetInstance()行之前调用Debug.WriteLine(ObjectFactory.WhatDoIHave())时,没有任何配置数据存在(我从global.asax中放置的同一个Debug行看到),我得到一个“调用GetInstance()时,没有为PluginFamily CPOP.Domain.Contracts.Repositories.IUserRepository定义的默认实例。这是为什么?好像我在MembershipProvider中有一个完全不同的容器。

3 个答案:

答案 0 :(得分:3)

在StructureMap中使用setter injection结束。可以通过调用:

来配置自定义MembershipProvider中的userRepository属性
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>(); });
    ...
}); 

然后,在目标实例上调用BuildUp()。我在Application_Start()中执行此操作,在调用所有注册表并且StructureMap具有所有配置数据之后。

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

完成。

答案 1 :(得分:0)

非常感谢你回答你的问题......这正是我所寻找的。

对我来说略有修改,诀窍是通过ObjectFactory配置一切(如上所述)并使用ObjectFactory的容器来处理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));

这样,一切都可以从Controller工厂的角度出发,并且MembershipProvider已经构建了#34;事后(因为它已经在Application_Start之前构建了,感谢.NET。)上面的代码是从Application_Start调用的。

答案 2 :(得分:0)

成员资格提供程序基本上是单例,这意味着ASP.NET只会创建单个实例。所以不要在私有字段/属性中保留任何内容,除非您希望在两个线程同时使用相同的成员资格提供程序时产生一些意外。

我只需要实现ValidateUser,因为我们不使用任何其他方法,我这样做:

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

当然,您需要配置DependencyResolver,StructureMap等,但重点是ISession不会保存在私有字段/属性中。