我有类似以下的内容:
interface IOuter { ... }
interface IInner { ... }
class Outer : IOuter {
public Outer(IInner inner) { ... }
}
class InnerA : IInner { ... }
class InnerB : IInner { ... }
我需要根据在命令行上传递的选项将InnerA
或InnerB
注入Outer
的构造函数。
根据我的调查,我有两种选择:
使用条件绑定:Bind<IInner>().To<InnerA>().When(_ => option == "useA")
,
以及InnerB
的类似绑定。
使用元数据:与Bind<IInner>().To<InnerA>().WithMetadata("option", "useA")
绑定并使用kernel.Get<IOuter>(metadata => metadata.Has("option") && metadata.Get<string>("option") == option)
解析
方法#1有效,但我将绑定放在一个模块中,该模块不能作为全局变量访问命令行option
。理想情况下,模块应仅依赖于解析期间传递的上下文信息。
这让我得到方法#2,但它不起作用,因为显然元数据仅适用于解析当前界面,即我的情况下IOuter
。在尝试解析Outer
的依赖关系时,它不适用,即IInner
,因此我从Ninject收到错误,它无法激活IOuter
(没有匹配的绑定)可用)。
第三种选择是使用kernel.Get<IOuter>(new ConstructorArgument("inner", ctx => ctx.Kernel.Get<IInner>(metadata => ...)))
,但它过于手动和冗长。如果链中存在多个需要类似逻辑的依赖项,它也会变得难以处理。
有没有办法根据解析根对象时传递的元数据有条件地绑定依赖关系(可能是依赖链中的几个级别),而不依赖于访问全局配置/选项?
答案 0 :(得分:0)
我需要根据命令行传递的选项将InnerA或InnerB注入外部构造函数。
换句话说,所选组件在应用程序的生命周期内不会改变。
这样做:
if (commandLineArg) {
Bind<IInner>().To<InnerA>();
} else {
Bind<IInner>().To<InnerB>();
}