C# Ninject-绑定类型列表

C# Ninject-绑定类型列表,c#,ninject,C#,Ninject,我正在使用Ninject。我要做的是映射类型为的列表,然后将其注入到我的类的构造函数中: private readonly IList<IDispatchFilter> m_Filters; public DispatchFilteringManager(IList<IDispatchFilter> filters) { m_Filters = filters; } 专用只读IList m_过滤器; 公共DispatchFilteringManager(ILi

我正在使用
Ninject
。我要做的是映射类型为的
列表
,然后将其注入到我的类的构造函数中:

private readonly IList<IDispatchFilter> m_Filters;

public DispatchFilteringManager(IList<IDispatchFilter> filters)
{
    m_Filters = filters;
}
专用只读IList m_过滤器;
公共DispatchFilteringManager(IList筛选器)
{
m_过滤器=过滤器;
}
我尝试过这种绑定:

Bind<IList<IDispatchFilter>>()
    .ToMethod(bindDecoyDispatchFilters)
    .InSingletonScope();

private IList<IDispatchFilter> bindDecoyDispatchFilters(IContext context)
{
    Bind<IDispatchFilter>().To<WindowsXpFilter>();

    IList<IDispatchFilter> result = context.Kernel.GetAll<IDispatchFilter>().ToList();

    return result;
}
Bind()
.ToMethod(BindDecyDispatchFilters)
.InSingletonScope();
私有IList BindDecyDispatchFilters(IContext上下文)
{
绑定()到();
IList result=context.Kernel.GetAll().ToList();
返回结果;
}
但是在我的构造函数中,我得到一个空的
列表

我无法找到这个简单任务的解决方案。

更改:

Bind<IList<IDispatchFilter>>()
    .ToMethod(bindDecoyDispatchFilters)
    .InSingletonScope();

private IList<IDispatchFilter> bindDecoyDispatchFilters(IContext context)
{
    Bind<IDispatchFilter>().To<WindowsXpFilter>();
    ...
}
Bind()
.ToMethod(BindDecyDispatchFilters)
.InSingletonScope();
私有IList BindDecyDispatchFilters(IContext上下文)
{
绑定()到();
...
}
致:

Bind().To();
绑定()
.ToMethod(BindDecyDispatchFilters)
.InSingletonScope();
私有IList BindDecyDispatchFilters(IContext上下文)
{
...
}
说明:

我们在
.ToMethod
绑定中为
T
使用的方法只有在调用
container.Get
时才会执行,而不是在此之前


当Ninject尝试在
BindDeCoydDispatchFilters
方法中解析
IList>
时,它会查找在此之前注册的
IDispatchFilter
的所有绑定,但未找到任何绑定。因此,ctor参数被解析为一个空集合。

很遗憾,在构造函数中没有收到任何项的原因是由于Ninject的方式。Ninject对
IList
的解析似乎不直观地查找所有(独立)注册的
,并将它们注入类中,使用
IList
,而不是实际使用显式注册的方法解析
IList

因此,
binddecydispatchfilters
(由
.ToMethod(binddecydispatchfilters)
绑定)将永远不会被调用,因为Ninject将根据注册的类型
T
解析
IList
。(这很容易测试-将断点或
Assert.Fail()
放在方法内部-它永远不会被调用)

所以如果

Bind<IDispatchFilter>().To<WindowsXpFilter>();
也可以完全删除
binddecodispatchfilters
方法

但是,如果在引导之后过滤器列表发生了变化,并且您确实需要一个动态工厂方法来将可用的过滤器返回给构造函数,那么您可以求助于一个动态工厂方法

或者,如果没有许多类依赖于
IList
,也可以显式注册每个类,这同样优先于多重注入,因此引导代码变为:

kernel.Bind<ResolveMe>()
     .ToSelf()
     .WithConstructorArgument<IEnumerable<IDispatchFilter>>(bindDecoyDispatchFilters);

private IList<IDispatchFilter> bindDecoyDispatchFilters(IContext context)
{
    // Contract.Assert(1 == 0); // .. .ensure the method is called during resolution!
    context.Kernel.Bind<IDispatchFilter>().To<WindowsXpFilter>();
    return context.Kernel.GetAll<IDispatchFilter>().ToList();
}
kernel.Bind()
.ToSelf()
.带有构造函数参数(BindDecyDispatchFilters);
私有IList BindDecyDispatchFilters(IContext上下文)
{
//Assert(1==0);/…确保在解析期间调用该方法!
context.Kernel.Bind().To();
返回context.Kernel.GetAll().ToList();
}
我用来测试的课程是:

public interface IDispatchFilter {}

public class WindowsXpFilter : IDispatchFilter { }

public class ResolveMe
{
    public IEnumerable<IDispatchFilter> Stuff { get; set; }

    public ResolveMe(IEnumerable<IDispatchFilter> stuff) { Stuff = stuff; }
}
公共接口IDispatchFilter{}
公共类WindowsXpFilter:IDispatchFilter{}
公共类解决方案
{
公共IEnumerable Stuff{get;set;}
公共解析(IEnumerable stuff){stuff=stuff;}
}
以及一些测试:

  var y = kernel.Get<ResolveMe>();
  Assert.IsTrue(y.Stuff.Any());
var y=kernel.Get();
Assert.IsTrue(y.Stuff.Any());

A
.ToMethod
binding很可能会执行该方法以获取实例,因为它发生在所有绑定都已完成的运行时,所以这一行将被忽略:
Bind()
。您可以将其移动到Ninject可以拾取它的外部作用域。@Fabjan好的,我会尝试更新IMO多重注入,但显式注册的IList的优先级需要优先于多重注入。
public interface IDispatchFilter {}

public class WindowsXpFilter : IDispatchFilter { }

public class ResolveMe
{
    public IEnumerable<IDispatchFilter> Stuff { get; set; }

    public ResolveMe(IEnumerable<IDispatchFilter> stuff) { Stuff = stuff; }
}
  var y = kernel.Get<ResolveMe>();
  Assert.IsTrue(y.Stuff.Any());