c# - 仅当属性不为 null 时才进行条件依赖注入(inject)绑定(bind)

标签 c# nhibernate dependency-injection ninject conditional-binding

它是一个桌面应用程序,在访问底层数据源时必须模拟当前用户。

如何告诉 Ninject 在父对象的属性不为 null 之前不要绑定(bind)依赖项?

  1. 应用程序在启动时强制进行用户身份验证
  2. 经过身份验证后,对当前用户凭据的引用将保存在 IMembershipService
  3. 访问底层数据源必须对用户进行身份验证,以便通信字符串指明要模拟的凭据

我实际上正在使用NHibernate,我需要根据身份验证时提供的用户凭据动态创建连接字符串。

所以我想实现:

public class DataModule : NinjectModule {
    public override void Load() {
        Bind<ISessionFactory>().ToProvider<SessionFactoryProvider>()
            .When( // IMembershipService.CurrentUser != null );
    } 
}

由于 SessionProviderFactory 依赖于 IMembershipService.CurrentUser

我知道这可能不是本世纪的设计,此外我现在需要它以这种方式工作,以便我可以交付我的可能可交付的产品。我很乐意稍后重构。

SessionFactoryProvider

public class SessionFactoryProvider : Provider<ISessionFactory> {
    public class SessionFactoryProvider(IMembershipService service) {
        membershipService = service;
    }

    protected override ISessionFactory CreateInstance(IContext context) {
        Configuration nhconfig = new Configuration().Configure();
        nhconfig.AddAssembly(Assembly.GetExecutingAssembly());
        nhconfig.Properties["connection.connection_string"] = buildConnectiongString();
        return nhconfig.BuildSessionFactory();
    }

    private string buildConnectionString() {
        return string.Format(membershipService.GetDefaultConnectionString()
            , membershipService.CurrentUser.DatabaseInstanceName
            , membershipService.CurrentUser.Login
            , membershipService.CurrentUser.Password);
    }

    private readonly IMembershipService membershipService;
}

SessionProvider

public class SessionProvider : Provider<ISession> {
    public class SessionProvider(ISessionFactory factory) {
        sessionFactory = factory;
    }

    protected override ISession CreateInstance(IContext context) {
        return sessionFactory.OpenSession();
    }

    private readonly ISessionFactory sessionFactory;
}

事实是,我无法在应用程序启动时实例化 IMembershipService.CurrentUser 。用户必须首先向系统进行身份验证,因此会出现 ActivationException

Error activating ISession

No matching bindings are available, and the type is not self-bindable.

Activation path:

3) Injection of dependency ISession into parameter session of constructor of type InquiriesRepository

2) Injection of dependency IInquiriesRepository into parameter repository of constructor of type InquiriesManagementPresenter

1) Request for InquiriesManagementPresenter

Suggestions:

1) Ensure that you have defined a binding for ISession.

2) If the binding was defined in a module, ensure that the module has been loaded into the kernel.

3) Ensure you have not accidentally created more than one kernel.

4) If you are using constructor arguments, ensure that the parameter name matches the constructors parameter name.

5) If you are using automatic module loading, ensure the search path and filters are correct.

那么,我该如何实现呢?

欢迎任何设计改进建议。但请记住,我非常需要它工作。我将在下次交付时进行重构。

EDIT

看起来我也许可以使用上下文/范围依赖注入(inject)。

How to use the additional Ninject Scopes of NamedScope

而且,我仍然不知道如何让它在我的场景中工作。

UPDATE

通过阅读,我开始怀疑上下文绑定(bind)是否比条件绑定(bind)更适合我的需求。

有什么想法吗?

每一篇涉及条件绑定(bind)的文章都在谈论条件类型绑定(bind),而不是条件状态绑定(bind)。

在我的场景中,它特别相信它是一个条件状态绑定(bind),因此产生了关于上下文绑定(bind)的想法。

然后,我将有两个绑定(bind)。

  1. 在用户通过身份验证之前
  2. 用户通过身份验证后

因此,也许我必须使用延迟注入(inject),这可以解决我的问题,因为应用程序启动时不需要 ISessionFactory 的实例。

我有点失落......

最佳答案

您也许能够创建条件绑定(bind):

IBindingRoot.Bind<IFoo>().To<Foo>()
    .When(request => request.ParentContext.Kernel.Get<IUserService>().AuthenticatedUser != null);

但我不推荐它;-)

@Pacane

每当请求 IFoo 时,就会执行 When 条件。它会转换为另一个请求,因此成本较高。

此外,此方法仅在存在父请求的情况下才有效。如果您执行IResolutionRoot.Get<IFoo>()它会抛出 NullReferenceException .

您可以通过访问语法提供的内核来解决这个问题。但我不知道它是否会在 ninject 的 future 版本中保留...


此外,拥有一个应用程序引导机制可以确保您仅在“完全初始化”(=> 经过身份验证)后实例化对象树的某些部分,这是一个更好的设计。至少在我看来。

关于c# - 仅当属性不为 null 时才进行条件依赖注入(inject)绑定(bind),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22793037/

相关文章:

c# - 如何在 C# 中获取类属性的属性值

c# - 帮我获取两个同名的分支第三方 dll,以便更好地发挥作用

c# - NHibernate 不更新多对多连接表

c# - Fluent NHibernate - 从映射覆盖表名

java - 如何注入(inject)或替换@Resource 依赖项?

c# - Microsoft.ApplicationInsights 错误 : InstrumentationKey cannot be empty

c# - 在 .NET 中开发新的 RESTful Web 服务——我应该从哪里开始? ASP.NET-MVC、WCF?

nhibernate - 使用 NHibernate 在插入时数据库生成日期

c# - 如何将 Controller Action 的参数传递给 Ninject 具体类型?

java - 如何在 Eclipse RCP 3.x 中提供依赖注入(inject)?