简体   繁体   English

Ninject泛型集合的隐式构造函数绑定错误

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM