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

Mat*_*don 3 c# dependency-injection ninject

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

我试过这个,其中包括:

// 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");
}
Run Code Online (Sandbox Code Playgroud)

但每次我进入构造函数时ConfigurationLoader,IEnumerable<ICommand>参数都不包含任何元素.无论是否有命名范围,我认为我需要告诉Ninject"看起来我有两个相同类型的绑定,我希望你给我两个相同的实例".

第一个绑定工作 - 我知道因为我的菜单项在点击时会做一些事情.但是ICommand注入(不是?!)的方式有问题ConfigurationLoader,我不知道如何修复它.

Bat*_*nit 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();
}
Run Code Online (Sandbox Code Playgroud)

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


结合现有When...条件有一种轻微的hackish方式.可以先创建绑定,没有任何条件,然后添加条件,检索它(它是a 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();
Run Code Online (Sandbox Code Playgroud)