【问题标题】:Ninject bound CustomMembershipProvider not calling Initialize methodNinject 绑定 CustomMembershipProvider 不调用 Initialize 方法
【发布时间】:2011-06-14 14:29:06
【问题描述】:

我创建了一个自定义成员资格提供程序,它在其构造函数中采用 IUsersRepository 的实例。

private IUsersRepository usersRepository;
public CustomMembershipProvider(IUsersRepository usersRepository)
{
     this.usersRepository = usersRepository;
}

这个依赖是使用 Ninject 绑定的

Bind<IUsersRepository>().To<SqlUsersRepository>().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["AppDb"].ConnectionString);
Bind<MembershipProvider>().To<CustomMembershipProvider>();

并像这样在我的 AccountController 中使用

CustomMembershipProvider provider;

public AccountController(MembershipProvider membershipProvider)
{
     this.provider = (CustomMembershipProvider)membershipProvider;
}

[HttpPost]
public ActionResult Register(User user)
{
    MembershipCreateStatus status = new MembershipCreateStatus();
    provider.CreateUser(user.FirstName, user.LastName, user.Email, user.Password, out status);

    return View(user);
}

这样做的问题是,当 CustomMembershipProvider 被实例化时,Initialize 方法没有被调用,因此我修改过的 Web.Config 没有被读取。

另一方面,我注意到 CustomMembershipProvider 被实例化了两次——第一次是我上面解释的,然后是当我的 [HttpPost] 操作方法被调用时。第二次使用无参数构造函数实例化它并调用 Initialize 方法。我不知道第二个 CustomMembershipProvider 会发生什么,因为 provider.CreateUser() 使用了我未初始化的 CustomMembershipProvider。

我希望我已经解释得足够好,任何帮助将不胜感激。

【问题讨论】:

  • 感谢您的评论,但如果我太天真,请原谅我 - 因为我没有使用 Windsor,所以我看不出这些链接如何帮助解决我的问题。
  • 几乎没有任何区别,相同的概念适用于 Ninject 或任何其他 IoC 容器,甚至很多代码。
  • @Mauricio 老实说,我真的不明白该怎么做 - 似乎有很多代码和乱七八糟的东西来解决这个问题。我很想删除 IUsersRepository 和 MembershipProvider 之间的依赖关系,并将我的存储库代码放在提供程序中,因为这是我将使用它的唯一地方。我确实意识到这会使测试变得困难。

标签: c# unit-testing asp.net-mvc-2 dependency-injection ninject


【解决方案1】:

我不知道您是否使用了 Ninject.Mvc3 扩展(您可能应该这样做),但这将允许您在每个 Web 请求中拥有一个 MembershipProvider 实例。您必须像这样进行绑定:

Bind<MembershipProvider>().To<CustomMembershipProvider>().InRequestScope();

如果你想每次都返回同一个实例,你可以使用 InSingletonScope。

在绑定往往在 Mvc 应用程序中完成时,访问 web.config 是不可能的,但我通常通过自定义配置部分并将其绑定到方法来解决这个问题。通过这样做,该方法将不会被评估,直到内核被要求提供配置部分,并且那时可以访问 web.config。类似的东西可能适用于您的连接字符串。

Bind<MyConfigurationSection>().ToMethod(context => (MyConfigurationSection)ConfigurationManager.GetSection("mysection")).InSingletonScope();

【讨论】:

  • 感谢您的回复。我没有使用 Mvc3 扩展,因为这是一个 Mvc2 应用程序(我对 ASP.net Mvc 比较陌生)。我尝试将 InRequestScope() 添加到我的项目中,它似乎第三次创建了我的自定义会员提供程序 - 我猜这会有所不同,因为我使用的是 Mvc2。
  • 请原谅我听起来很笨,但您能否详细说明您访问 web.config 的答案?我可以通过从我的 CustomMembershipProvider 的构造函数(使用 IUsersRepository 的那个)调用的方法中读取我的配置值来实现同样的事情吗?这意味着 base.Initialize 不会被调用——这有关系吗?
【解决方案2】:
Public Class SomeRolProvider
    Inherits RoleProvider
    Implements IProvider

    'this service needs to get initialized
    <Inject()>
    Public Property _memberhip As IMemberschipService


    Sub New()
        'only this constructor is called
    End Sub



Protected Overrides Function CreateKernel() As Ninject.IKernel
            Dim modules = New NinjectModule() {New Anipmodule()}

            Dim kernel = New StandardKernel(modules)
            kernel.Inject(Roles.Provider)
            kernel.Inject(Membership.Provider)
            Return kernel
        End Function

这将强制内核绑定成员芯片提供者的属性

【讨论】:

  • 感谢您的回复,但这并不能解决我的问题。绑定时仍无法访问 Web.config。
【解决方案3】:

感谢大家对这个问题的帮助。在不需要大量代码的情况下,我无法找到适合这种应用情况的解决方案。

为了解决这个问题,我查看了默认的 MVC 2 项目并复制了一些 Microsoft 的代码。我的项目可能不是很容易测试,但我需要一个快速的解决方案。我已经设置好了,如果将来有时间找到解决方案,我可以用当前代码替换它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-25
    相关资源
    最近更新 更多