Причина, по которой вы не получаете никаких элементов в конструкторе, к сожалению, связана с тем, как Ninject's Multi Injection работает .Разрешение Ninject IList<T>
, кажется, не интуитивно ищет все (независимо) зарегистрированные <T>
и вводит их в ваш класс, принимая IList<T>
, вместо того, чтобы фактически использовать явно зарегистрированный метод для разрешения IList<T>
.
В результате bindDecoyDispatchFilters
(как ограничено .ToMethod(bindDecoyDispatchFilters)
) никогда не будет вызвано, поскольку Ninject вместо этого разрешит IList<T>
на основе зарегистрированных типов T
.(Это легко проверить - поставить точку останова или Assert.Fail()
внутри метода - он никогда не вызывается).
Так что, если
Bind<IDispatchFilter>().To<WindowsXpFilter>();
является единственным IDispatchFilter
, которыйкогда-нибудь нужно разрешить в IList
, тогда вы можете отказаться от регистрации, и, согласно @ Fabjan's, напрямую зарегистрировать Bind<IDispatchFilter>().To<WindowsXpFilter>();
.Мультиинжекция разрешит это как отдельный элемент в IList<T>
, переданном вашему конструктору.
Затем вы можете полностью удалить привязку IList<T>
:
Bind<IList<IDispatchFilter>>() ... remove
.ToMethod(bindDecoyDispatchFilters)
.InSingletonScope();
, а также отброситьbindDecoyDispatchFilters
метод полностью.
Однако, если список фильтров изменяется после начальной загрузки, и вам нужен динамический фабричный метод для возврата доступных фильтров вашим конструкторам, тогда вы можете прибегнуть к взломать, как это .
В качестве альтернативы, если у вас мало классов, зависящих от IList<>
, вы также можете явно зарегистрировать каждый класс, который снова имеет приоритет над мультиинжекцией, так что Bootstrappingкод становится:
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();
}
Классы, которые я использовал для тестирования:
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());