2016-04-16 6 views
0

У меня есть интерфейс, допустим, это IDrawingTool. У меня есть несколько классов, реализующих этот интерфейс, допустим, PencilTool, PenTool, YellowMarkerTool и т. Д. Я обычно связываю более одного из этих классов в Ninject, и я всегда получаю доступ к экземплярам IDrawingTool, вызывая kernel.GetAll<IDrawingTool>. Все идет нормально.Создание пользовательского поставщика Ninject для нескольких типов, реализующих один и тот же интерфейс

Теперь я хочу создать новую реализацию IDrawingTool, которая может быть настроена различными способами (скажем, цвет кисти, толщина кисти и т. Д.).

Я хотел бы иметь какой-то «фабричный»/«провайдер», который позволит мне вводить несколько IDrawingTool s (т. Е. Несколько ConfigurableBrushTool s с различными конфигурациями). То есть, я хочу, чтобы иметь возможность сделать что-то вроде следующего:

kernel.Bind<IDrawingTool>.To<PencilTool>(); 
kernel.Bind<IDrawingTool>.To<PenTool>(); 
kernel.Bind<IDrawingTool>.ToTypeProvider<ConfigurableBrushToolProvider>(); 
//...where ConfigurableBrushToolProvider reads e.g. 50 different 
//brush configurations (color, thickness, etc) from the database/file/network/whatever 
//and binds 50 different ConfigurableBrushTool instances. 
//Of course, .ToTypeProvider() doesn't really exist :) 

//Later on: 
var tools = kernel.GetAll<IDrawingTool>(); //Should return pencil, pen and all 50 brushes 

Я не смог найти способ, чтобы это произошло с Ninject.

Я посмотрел на реализацию IProvider/Provider<T>, но это только позволяет мне возвратить один экземпляр типа, который я предоставляю, нет способа вернуть несколько экземпляров навалом.

Я также посмотрел на IMissingBindingResolver, и это очень близко к тому, что мне нужно: Если я создаю такой распознаватель для IDrawingTool, я могу вернуть несколько привязок для нескольких ConfigurableBrushTool с. Однако он работает только в том случае, если привязка отсутствует (т. Е. Если нет других привязок IDrawingTool). Как только я добавляю привязки PenTool и PencilTool, привязка для IDrawingTool больше не «отсутствует», и поэтому мой пользовательский резольвер больше не вызывается.

Есть ли способ сделать мой сценарий? То есть как я могу привязать интерфейс к (1) конкретным типам, реализующим интерфейс, и (2) «фабричный»/«поставщик» многих экземпляров, реализующих интерфейс, так что GetAll вернет все привязки, как (1) и (2)?

ответ

1

Прежде всего, похоже, что нет функции OOTB, чтобы сделать несколько привязок из одного набора привязки в модуле (по крайней мере, я не нашел очевидного).
Во-вторых, мне удалось создать PoC с настраиваемым ядром, которое позволяет вам создавать привязки «один ко многим» с одним вызовом .Bind.To. Is основан на переопределении метода IKernel.GetBindings(..) и поиске всех привязок со специальным параметром. Затем мы можем удалить их, заменив их на количество созданных пользователем.
Однако, я думаю, что такая логика окажет огромное влияние на производительность, если не будет тщательно оптимизирована (что еще не сделано для PoC) и должно сделать это для производства, только если это действительно необходимо. Это PoC вы можете найти here.
Что касается меня, это гораздо лучший подход к рефакторингу существующего кода для ввода фабричного возвращаемого массива, созданного «на лету».

+0

Спасибо! Слишком плохо, что нет готового способа сделать это ... Я ценю работу, которую вы вложили в это, несмотря на то, что ваш код достигает именно того, что мне нужно (хотя реалистично я, вероятно, выберу рефакторинг подход), но в любом случае, ваша щедрость. –

+0

Спасибо, Юджин, надеюсь, что этот пример в любом случае поможет вам понять возможности Ninject. –

0

Как насчет привязки пользовательской коллекции (обходя мульти-инъекции), как:

public interface IToolList : IReadOnlyList<IDrawingTool> {} 

и есть его реализация вернуть оба, связанные инструменты и те, «созданные» из базы данных, что-то вроде:

public class ToolList : List<IDrawingTool>, IToolList 
{ 
    public ToolList(IDrawingTool[] boundTools,... otherDependencies) 
    { 
     ... create all tools here 
    } 
} 
+0

Существует большая существующая кодовая база, которая уже делает GetAll в нескольких местах - я бы не стал изменять все эти места, чтобы использовать IToolList (также другой разработчик по этой линии не будет знать, что в специальном в случае IDrawingTool вам нужно получить к нему доступ через IToolList, а не только стандартный GetAll). Чтобы быть ясным, мой реальный прецедент касается не инструментов рисования, а сложных бизнес-объектов:), есть еще много вещей Ninject-ed. Ваш ответ работает как обходной путь, но я хотел бы знать, можно ли сделать Ninject делать то, что мне нужно. –

 Смежные вопросы

  • Нет связанных вопросов^_^