[英]Ninject Implicit constructor binding error for generic collections
Consider the following code: 考虑以下代码:
using System.Collections.ObjectModel;
using Ninject;
namespace ConsoleApplication2 {
public interface IComponent {
//stuff
}
public class Component : IComponent {
// implementation of stuff
}
public class Aggregator {
private ObservableCollection<IComponent> _componentList;
public Aggregator(ObservableCollection<IComponent> componentList) {
_componentList = componentList;
}
public ObservableCollection<IComponent> ComponentList { get { return _componentList; } }
}
public class Bindings : Ninject.Modules.NinjectModule {
public override void Load() {
Bind<IComponent>().To<Component>();
}
}
public class MyProgram {
public static void Main() {
Ninject.IKernel kernel = new StandardKernel(new Bindings());
var myAgg = kernel.Get<Aggregator>();
}
}
}
For me this fails with a run-time exception of: 对我来说,这会失败,并出现以下运行时异常:
Ninject.ActivationException was unhandled HResult=-2146233088 Message=Error activating ObservableCollection{IComponent} using implicit self-binding of ObservableCollection{IComponent} Several constructors have the same priority. 未处理Ninject.ActivationException HResult = -2146233088消息=使用ObservableCollection {IComponent}的隐式自绑定激活ObservableCollection {IComponent}时出错。几个构造函数具有相同的优先级。 Please specify the constructor using ToConstructor syntax or add an Inject attribute. 请使用ToConstructor语法指定构造函数,或添加一个Inject属性。
Constructors: ObservableCollection 1(List{IComponent} list) [__DynamicallyInvokable]ObservableCollection
1(IEnumerable{IComponent} collection) 构造函数:ObservableCollection 1(List{IComponent} list) [__DynamicallyInvokable]ObservableCollection
1(IEnumerable {IComponent}集合)
Activation path: 2) Injection of dependency ObservableCollection{IComponent} into parameter componentList of constructor of type Aggregator 1) Request for Aggregator 激活路径:2)将依赖项ObservableCollection {IComponent}注入到参数component中,类型为Aggregator的构造函数的列表1)请求Aggregator
Suggestions: 1) Ensure that the implementation type has a public constructor. 建议:1)确保实现类型具有公共构造函数。 2) If you have implemented the Singleton pattern, use a binding with InSingletonScope() instead. 2)如果您已经实现了Singleton模式,请使用InSingletonScope()绑定。
Source=Ninject StackTrace: at Ninject.Activation.Providers.StandardProvider.Create(IContext context) at Ninject.Activation.Context.ResolveInternal(Object scope) at Ninject.Activation.Context.Resolve() at Ninject.KernelBase.<>c__DisplayClass15.b__f(IBinding binding) at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable
1 source) at Ninject.Planning.Targets.Target 1.GetValue(Type service, IContext parent) at Ninject.Planning.Targets.Target
1.ResolveWithin(IContext parent) at Ninject.Activation.Providers.StandardProvider.GetValue(IContext context, ITarget target) at Ninject.Activation.Providers.StandardProvider.<>c__DisplayClass4.b__2(ITarget target) at System.Linq.Enumerable.WhereSelectArrayIterator 2.MoveNext() at System.Linq.Buffer
1..ctor(IEnumerable 1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1 source) at Ninject.Activation.Providers.StandardProvider.Create(IContext context) at Ninject. Source = Ninject StackTrace:位于Ninject.Activation.Providers.StandardProvider.Create(IContext上下文)位于Ninject.Activation.Context.ResolveInternal(Object作用域)位于Ninject.Activation.Context.Resolve()位于Ninject.KernelBase。<> c__DisplayClass15。 b__f(IBinding绑定)位于System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable
1源)位于Ninject.Planning.Targets.Target 1.GetValue(Type service, IContext parent) at Ninject.Planning.Targets.Target
1.ResolveWithin(IContext parent)在Ninject.Activation.Providers.StandardProvider.GetValue(IContext context,ITarget target)在Ninject.Activation.Providers.StandardProvider。<> c__DisplayClass4.b__2(ITarget) target)位于System.Linq.Enumerable.WhereSelectArrayIterator 2.MoveNext() at System.Linq.Buffer
1..ctor(IEnumerable 1 source) at System.Linq.Enumerable.ToArray[TSource](IEnumerable
1源)位于Ninject.Activation Ninject的.Providers.StandardProvider.Create(IContext上下文)。 Activation.Context.ResolveInternal(Object scope) at Ninject.Activation.Context.Resolve() at Ninject.KernelBase.<>c__DisplayClass15.b__f(IBinding binding) at System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.<CastIterator>d__b1
1.MoveNext() at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source) at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) at ConsoleApplication2.MyProgram.Main() in C:\\Users\\user.name\\workspace\\vs2010\\ConsoleApplication2\\ConsoleApplication2\\Program.cs:line 36 at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() at System.Threading.ThreadHelper.ThreadStart_Context(Object state) at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object Ninject.Activation.Context.Resolve()位于Ninject.KernelBase的Activation.Context.ResolveInternal(Object scope).System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext()处于System.Linq.Enumerable.WhereSelectEnumerableIterator 2.MoveNext() at System.Linq.Enumerable.<CastIterator>d__b1
1.在ConsoleApplication2的Ninject.ResolutionExtensions.Get [T](IResolutionRoot根,IParameter []参数)处,System.Linq.Enumerable.Single [TSource](IEnumerable`1源)处的MoveNext()。 C:\\ Users \\ user.name \\ workspace \\ vs2010 \\ ConsoleApplication2 \\ ConsoleApplication2 \\ Program.cs中的MyProgram.Main()在System.AppDomain._nExecuteAssembly(RuntimeAssembly Assembly,String [] args)在System.AppDomain.ExecuteAssembly (位于Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()处的System.Threading.ThreadHelper.ThreadStart_Context(对象状态)处的System.Threading.ExecutionContext.RunInternal(ExecutionContext执行上下文,ContextCallback回调)处的(string assemblyFile,Evidence assemblySecurity,String [] args) ,对象 state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx) at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) at System.Threading.ThreadHelper.ThreadStart() InnerException: 状态,位于System.Threading.ExecutionContext.Run(ExecutionContext执行上下文,ContextCallback回调,对象状态,布尔值saveSyncCtx),位于System.Threading.ExecutionContext.Run(位于System.Threading.ExecutionContext.Run(ExecutionContext执行上下文,ContextCallback回调,对象状态),位于System.Threading.ThreadHelper .ThreadStart()InnerException:
The error is being caused by the ObservableCollection implicit constructor binding. 该错误是由ObservableCollection隐式构造函数绑定引起的。 Can somebody provide any ideas or pointers on how to resolve this? 有人可以提供任何想法或指示来解决此问题吗?
As ninject says, it doesn't know how to construct the ObservableCollection<>
because it has two publicly accessible constructors with the same argument count. 正如ninject所说,它不知道如何构造ObservableCollection<>
因为它有两个具有相同参数计数的可公开访问的构造函数。
When there are multiple constructors, ninject checks for which it can resolve the most arguments, and chooses this constructor. 当有多个构造函数时,ninject检查它可以解析最多参数的对象,并选择该构造函数。 There are 有
ObservableCollection<T>(IEnumerable<T>)
ObservableCollection<T>(List<T>)
both of which ninject could use (as long as you have defined a binding for T
). 这两个ninject都可以使用(只要您已经定义了T
的绑定)。
Now, the easiest way to override that behavior would be to place an [Inject]
attribute on the ctor you want ninject to use. 现在,覆盖该行为的最简单方法是将[Inject]
属性放在要ninject使用的ctor上。 Since the source code of ObservableCollection<>
is not under your control, you can't do it . 由于ObservableCollection<>
的源代码不受您的控制,因此您不能这样做。 What you can do is specifying a binding for the ObservableCollection<>
which tells Ninject how to create it. 您可以做的是为ObservableCollection<>
指定一个绑定,该绑定告诉Ninject如何创建它。 You can do this using the .ToConstructor()
syntax (as the exception stated): 您可以使用.ToConstructor()
语法(作为例外说明)执行此操作:
kernel
.Bind<ObservableCollection<IComponent>>()
.ToConstructor(x =>
new ObservableCollection<IComponent>(x.Inject<IList<IComponent>>()));
In theory you also could use the .ToMethod()
binding, but i would not recommend it. 从理论上讲,您也可以使用.ToMethod()
绑定,但是我不建议这样做。 Also see What's the difference between .ToConstructor and .ToMethod in Ninject 3? 另请参阅Ninject 3中的.ToConstructor和.ToMethod有什么区别?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.