Ninject在Kernel.Get和Constructor Injection之间的不同行为

我有什么:

public interface IBla { } public class Bla1 : IBla { } public class Bla : IBla { } public class Consumer { private readonly IBla[] _array; public Consumer(IBla[] array) { _array = array; } } public static class NinjectExtensions { public class BindListExpression { private readonly IKernel _kernel; private readonly List _types = new List(); public BindListExpression(IKernel kernel) { _kernel = kernel; } public BindListExpression ImplementedBy() where T : TElement { var type = typeof(T); _kernel.Bind().To(type); _types.Add(type); return this; } public void Bind() { Func createObjects = () => { var sourceArray = new TElement[_types.Count]; for (var i = 0; i < _types.Count; i++) { var value = _kernel.Get(_types[i]); sourceArray[i] = (TElement)value; } return sourceArray; }; _kernel.Bind().ToMethod(x => createObjects().ToArray()); _kernel.Bind<List>().ToMethod(x => (createObjects().ToList())); _kernel.Bind<IEnumerable>().ToMethod(x => createObjects().ToList()); } } public static BindListExpression ListOf(this IKernel kernel) { return new BindListExpression(kernel); } } 

用法:

 // Binds items in the given order as a list (Ninject does not guarantee the given order so I use this mechanism). kernel.ListOf() .ImplementedBy() .ImplementedBy() .Bind(); var consumer = kernel.Get(); // result: consumer._array is empty?! --> what is imo wrong var array = kernel.Get(); // result: Bla1, Bla --> correct 

为什么Ninject在Get()和带有参数IBla[]构造函数之间产生相同的结果?

使用构造函数注入,ninject将ctor参数IBla[]转换为IResolutionRoot.GetAll().ToArray() 。 这就是如何实现对多次注射的支持。 因此,ctor-request不可能产生IResolutionRoot.Get() – 但它仍然可以手动完成。

对于ninject转换为多次注入(AFAIR数组, IListIEnumerable ,但不是ICollection )的所有集合类型都是如此。

我建议使用另一个集合接口(如ICollection )或集合实现作为构造函数参数。 这将导致ctor-injection和IResolutionRoot.Get调用的一致行为。

可以按特定顺序绑定数组依赖项。 你只需要在Ninject注册它们就像这样。

 _kernel.Bind().ToSelf(); _kernel.Bind().ToSelf(); _kernel.Bind().To() .WithConstructorArgument("array", new IBla[] { _kernel.Get(), _kernel.Get() });