2015-04-29 1 views
1

Я хочу, чтобы Ninject разрешал экземпляр T на основе определенного значения ввода enum.Ninject factory create T основано на перечислении

Я читал о заводских расширениях Ninject, но я не смог найти ни одного примера, когда фабрика решила определенный класс на основе перечисления.

Каждый класс происходит от базового класса, и этот производный класс имеет несколько различных интерфейсов, которые Ninject также должен решить.

Например, это то, как должен выглядеть интерфейс:

public interface IProcessFactory 
{ 
    T Create<T>(ProcessIndex processIndex) where T : BaseProcess; 
} 

Как это может быть достигнуто?

ответ

0

Есть несколько вариантов для реализации AbstractFactory с помощью DI (Ninject).

После анализа вариантов, я пришел с решением, представленной Mark Seemann см http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/

Решение контейнер на базе завода один я выбрал, потому что:

  • Производительность: по запросу DI разрешение по запросу, экземпляры не загружены в конструктор
  • Легко для рефакторинга: если мы хотим заменить текущий каркас DI (Ninject) на гораздо лучший исполнитель с (почти или даже лучше) набором функций, единственное место для изменения - это звонки внутри фабрики, а не в N Инъекционные модули/Корень композиции.

Смотрите также на SO: Simple Injector:Factory classes that need to create classes with dependencies

3

Это не поддерживается из коробки. Вы можете настроить его, написав собственную реализацию IInstanceProvider (также см ninject Wiki entry Затем настройте его для конкретного завода:.

kernel.Bind<IFooFactory>() 
     .ToFactory(() => new MyCustomInstanceProvider()); 

или в качестве альтернативы, если вы хотите изменить поведение всех .ToFactory() привязок: пересвяжите IInstanceProvider после загрузки Ninject.Extensions.Factory:.

kernel.Rebind<IInstanceProvider>().To<MyCustomInstanceProvider>(); 

Однако, если это не то, что вам часто я хотел бы рассмотреть вручную писать реализации завода корень @ состав

В любом случае, в обоих случаях вам нужно будет знать, как создать условную привязку. Ninject называет его Contextual Binding. Один из способов заключается в использовании Binding-метаданные:

const string EnumKey = "EnumKey"; 

Bind<IFoo>().To<AFoo>() 
      .WithMetadata(EnumKey, MyEnum.A); 

IResolutionRoot.Get<IFoo>(x => x.Get<MyEnum>(EnumKey) == MyEnum.A); 

Другим способом было бы создать собственный IParameter и использовать в условном связывания:

Bind<IFoo>().To<AFoo>() 
      .When(x => x.Parameters.OfType<MyParameter>().Single().Value == A); 
+2

Лучше использовать kernel.Bind () .ToFactory (() => новый MyCustomInstanceProvider()); Это позволит вам определить, какой поставщик экземпляра следует использовать для конкретной фабричной привязки. – treze

+0

@treze благодарит, что это хороший момент, я включу его в свой пост. Однако мы сделали несколько дополнительных функций для InstanceProvider, которые мы использовали во многих местах.В этом случае я думаю, что на самом деле лучше предоставить его «глобально» вместо конкретного для привязки. – BatteryBackupUnit

+0

Если вы хотите, чтобы это был поставщик экземпляра по умолчанию, он, конечно же, имеет смысл – treze

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