注入 InSingletonScope 的对象是否也可以注入到其他地方的多重绑定中?
Can an object injected InSingletonScope be also injected in a multi-binding elsewhere?
我需要绑定 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 "look I have these two bindings for the same type, and I want you to give me the same instance for both".
第一个绑定有效 - 我知道是因为我的菜单项在被单击时会执行某些操作。但是 ICommand
注入 ConfigurationLoader
的方式有问题(不是?!),我不确定如何修复它。
据我所知,命名范围在这里毫无意义:
DefinesNamedScope
定义命名作用域的根
InNamedScope
确保根的依赖树中只有一个 T
实例。这也意味着一旦根对象被垃圾收集,它就会被处理掉。
当您希望所有命令都在单例范围内时,请不要使用其他命令。此外,只要 ConfigurationLoader
不是菜单项的(瞬态)依赖项,无论如何 InNamedScope
都不会实现。
此外,InSingletonScope()
应用于每个绑定。 IE。如果您有两个相同类型的绑定,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...
条件的方法有点老套。
可以先创建没有任何条件的绑定,然后添加条件、检索它(它是一个 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();
我需要绑定 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 "look I have these two bindings for the same type, and I want you to give me the same instance for both".
第一个绑定有效 - 我知道是因为我的菜单项在被单击时会执行某些操作。但是 ICommand
注入 ConfigurationLoader
的方式有问题(不是?!),我不确定如何修复它。
据我所知,命名范围在这里毫无意义:
DefinesNamedScope
定义命名作用域的根InNamedScope
确保根的依赖树中只有一个T
实例。这也意味着一旦根对象被垃圾收集,它就会被处理掉。
当您希望所有命令都在单例范围内时,请不要使用其他命令。此外,只要 ConfigurationLoader
不是菜单项的(瞬态)依赖项,无论如何 InNamedScope
都不会实现。
此外,InSingletonScope()
应用于每个绑定。 IE。如果您有两个相同类型的绑定,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...
条件的方法有点老套。
可以先创建没有任何条件的绑定,然后添加条件、检索它(它是一个 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();