注入InSingletonScope的对象是否也可以在其他地方注入多重绑定?

时间:2016-03-29 05:58:53

标签: c# dependency-injection ninject

我需要将ICommand绑定到特定的实现,当完全注入特定类型时(通过命名约定),然后我还需要一个具有多重绑定的类型一个IEnumerable<ICommand>构造函数参数 - 并且需要接收相同的实例,因为我需要我的命令 InSingletonScope

我试过这个,其中包括:

// note: ICommandMenuItem naming convention for [Foo]Command: [Foo]CommandMenuItem
var item = types.SingleOrDefault(type => type.Name == commandName + "CommandMenuItem");
if (item != null)
{
    _kernel.Bind<ICommand>().To(command)
           .WhenInjectedExactlyInto(item)
           .InSingletonScope()
           .DefinesNamedScope("commands");

    _kernel.Bind<ICommand>().To(command)
           .WhenInjectedExactlyInto<ConfigurationLoader>()
           .InNamedScope("commands");
}

但每次我闯入ConfigurationLoader的构造函数时,IEnumerable<ICommand>参数都不包含任何元素。无论是否有命名的范围,我思考我需要告诉Ninject&#34;看看我有两个相同类型的绑定,我希望你给我两个&的相同实例#34;

第一个绑定有效 - 我知道,因为我的菜单项在点击时会执行某些操作。但ICommand注入ConfigurationLoader的方式出现了问题(不是?!),我不确定如何修复它。

1 个答案:

答案 0 :(得分:5)

据我所知,命名范围在这里没有意义:

  • DefinesNamedScope定义命名范围的根
  • InNamedScope确保根目录的依赖树中只有T的一个实例。这也意味着一旦根对象被垃圾收集,它就会被处理掉。

当您希望所有命令都在Singleton范围内时,请不要使用其他命令。此外,只要ConfigurationLoader不是菜单项的(瞬态)依赖关系,无论如何都不会满足InNamedScope

此外,每个绑定都应用InSingletonScope()。即如果您有两个相同类型的绑定,InSingletonScope()将(可能)导致两个实例。这就是为什么有Bind(Type[])重载,你可以将多个服务绑定到一个分辨率。

您需要拥有的是具有OR条件的单一绑定:

// note: ICommandMenuItem naming convention for [Foo]Command: [Foo]CommandMenuItem
var item = types.SingleOrDefault(type => type.Name == commandName + "CommandMenuItem");
if (item != null)
{
    _kernel.Bind<ICommand>().To(command)
           .WhenInjectedExactlyIntoAnyOf(item, typeof(ConfigurationLoader))
           .InSingletonScope();
}

现在,当然,WhenInjectedExactlyIntoAnyOf不可用。另外,令人遗憾的是,ninject并没有采用开箱即用的方式来结合现有条件。所以,你必须根据When(Func<IRequest,bool> condition)推出自己的条件。

结合现有的When...条件有一种轻微的hackish方式。 可以先创建绑定,没有任何条件,然后添加条件,检索它(它是Func<IRequest,bool>),然后替换条件,检索它,组合它,替换它......等等。

// example binding without condition
var binding = kernel.Bind<string>().ToSelf();

// adding an initial condition and retrieving it
Func<IRequest, bool> whenIntegerCondition = binding.WhenInjectedInto<int()
    .BindingConfiguration.Condition;

// replacing condition by second condition and retrieving it
Func<IRequest, bool> whenDoubleCondition = binding.WhenInjectedInto<double>().
    BindingConfiguration.Condition;

// replacing the condition with combined condition and finishing binding
binding.When(req => whenIntCondition(req) || whenDoubleCondition(req))
       .InSingletonScope();