2

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

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

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

我实际上使用的是 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;
}

会话提供者

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.

激活 ISession 时出错

没有匹配的绑定可用,并且该类型不可自绑定。

激活路径:

3) InquiriesRepository 类型的构造函数的参数 session 中注入依赖 ISession

2) 将依赖 IInquiriesRepository 注入到 InquiriesManagementPresenter 类型的构造函数的参数存储库中

1) 询价管理Presenter

建议:

1) 确保您已经为 ISession 定义了绑定。

2) 如果绑定是在模块中定义的,请确保该模块已加载到内核中。

3) 确保您没有意外创建多个内核。

4) 如果您使用构造函数参数,请确保参数名称与构造函数参数名称匹配。

5) 如果您使用自动模块加载,请确保搜索路径和过滤器正确。

那么,我该怎么做呢?

欢迎任何设计改进建议。但请记住,我需要它才能正常工作。我将为下一次交付进行重构。

编辑

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

How to use the additional Ninject Scopes of NamedScope

而且,我仍然无法弄清楚如何让它在我的场景中工作。

更新

通过我的阅读,我开始怀疑上下文绑定可能比条件绑定更适合我的需要。

有什么想法吗?

每篇与条件绑定相关的文章都在谈论条件类型绑定,而不是条件状态绑定。

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

然后,我将有两个绑定。

  1. 在用户被认证之前
  2. 用户认证后

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

我在这里有点失落......

4

1 回答 1

3

您也许可以创建条件绑定:

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

但我不推荐它;-)

@Pacane

每次请求 IFoo 时都会执行 When 条件。它转换为另一个请求,因此有点昂贵。

此外,这种方法仅在有父请求的情况下才有效。如果你做 aIResolutionRoot.Get<IFoo>()它会抛出一个NullReferenceException.

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


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

于 2014-04-03T15:32:09.637 回答