如何在不依赖全局配置的情况下有条件地绑定深度依赖?

时间:2014-03-11 17:15:51

标签: ninject

我有类似以下的内容:

interface IOuter { ... }
interface IInner { ... }

class Outer : IOuter {
    public Outer(IInner inner) { ... }
}

class InnerA : IInner { ... }
class InnerB : IInner { ... }

我需要根据在命令行上传递的选项将InnerAInnerB注入Outer的构造函数。

根据我的调查,我有两种选择:

  1. 使用条件绑定:Bind<IInner>().To<InnerA>().When(_ => option == "useA"), 以及InnerB的类似绑定。

  2. 使用元数据:与Bind<IInner>().To<InnerA>().WithMetadata("option", "useA")绑定并使用kernel.Get<IOuter>(metadata => metadata.Has("option") && metadata.Get<string>("option") == option)解析

  3. 方法#1有效,但我将绑定放在一个模块中,该模块不能作为全局变量访问命令行option。理想情况下,模块应仅依赖于解析期间传递的上下文信息。

    这让我得到方法#2,但它不起作用,因为显然元数据仅适用于解析当前界面,即我的情况下IOuter。在尝试解析Outer的依赖关系时,它不适用,即IInner,因此我从Ninject收到错误,它无法激活IOuter(没有匹配的绑定)可用)。

    第三种选择是使用kernel.Get<IOuter>(new ConstructorArgument("inner", ctx => ctx.Kernel.Get<IInner>(metadata => ...))),但它过于手动和冗长。如果链中存在多个需要类似逻辑的依赖项,它也会变得难以处理。

    有没有办法根据解析根对象时传递的元数据有条件地绑定依赖关系(可能是依赖链中的几个级别),而不依赖于访问全局配置/选项?

1 个答案:

答案 0 :(得分:0)

  
    

我需要根据命令行传递的选项将InnerA或InnerB注入外部构造函数。

  

换句话说,所选组件在应用程序的生命周期内不会改变。

这样做:

if (commandLineArg) {
    Bind<IInner>().To<InnerA>();
} else {
    Bind<IInner>().To<InnerB>();
}