仅当属性不为空时才进行条件依赖注入绑定 [英] Conditional dependency injection binding only when property not null

查看:27
本文介绍了仅当属性不为空时才进行条件依赖注入绑定的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

It is a desktop application which is obliged to impersonate the current user when accessing the underlying data source.

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

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

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

I am actually using NHibernate, and I need to dynamically create the connection string based on the user credentials provided upon authentication.

所以我想实现:

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

由于 SessionProviderFactory 依赖于 IMembershipService.CurrentUser.

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

I am aware this might not be the design of the century, beside I need it to work this way for now so that I can deliver my piece of potentially shippable product. I'll be glad to refactor afterwards.

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.

The fact is that I can't instantiate the IMembershipService.CurrentUser upon application startup. The user has first to authenticate to the system, hence the ActivationException.

激活 ISession 时出错

Error activating ISession

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

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

激活路径:

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

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

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

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

1) 请求查询ManagementPresenter

1) Request for InquiriesManagementPresenter

建议:

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

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

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

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

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

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

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

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

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

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

那么,我该怎么做呢?

欢迎提出任何设计改进建议.但请记住,我需要它才能正常工作.我将重构以备下次交付使用.

Any design improvement suggestions welcome. But keep in mind that I need it to work badly. I'll refactor for the next delivery.

编辑

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

It looks like I perhaps could use contexts/scope dependency injection.

如何使用NamedScope的额外Ninject Scopes

而且,我仍然不知道如何让它在我的场景中发挥作用.

And still, I cannot figure out how to make it work here in my scenario.

更新

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

Through my readings, I begin to doubt that perhaps contextual binding would be more suitable for my needs than conditional binding.

有什么想法吗?

每篇关于条件绑定的文章都在讨论条件类型绑定,而不是条件状态绑定.

Each article which relates on conditional binding is talking about conditional type binding, not conditional state binding.

在我的场景中,它特别相信它是一个有条件的状态绑定,因此有关于上下文绑定的想法.

In my scenario, it specifically believe it is a conditional state binding, hence the thoughts about context binding.

然后,我会有两个绑定.

Then, I would have two bindings.

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

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

So perhaps I either have to use lazy injection, which would resolve my problem, as an instance of the ISessionFactory isn't required on application startup.

我有点不知所措...

推荐答案

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

You might be able to create a conditional binding:

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

但我不推荐它;-)

@Pacane

When 条件将在每次请求 IFoo 时执行.它会转化为另一个请求,因此成本有点高.

The When condition will be executed every time one requests an IFoo. It translates to another request and is thus somewhat costly.

此外,这种方法仅在有父请求的情况下才有效.如果你执行了 IResolutionRoot.Get(),它会抛出一个 NullReferenceException.

Also, this approach only works in case there is a parent request. In case you do a IResolutionRoot.Get<IFoo>() it will throw a NullReferenceException.

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

You could work around that by accessing the kernel provided by the syntax. But i don't know whether it's going to stay there in future releases of ninject...

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

Also, having an application bootstrapping mechanism which ensures that you only instanciate certain parts of the object tree after you are "fully initialized" (=> authenticated) is a better design. At least in my opinion.

这篇关于仅当属性不为空时才进行条件依赖注入绑定的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆