2010-02-09 5 views
61

Я решил начать использовать Ninject и столкнуться с проблемой. Скажем, у меня есть следующий сценарий. У меня есть интерфейс IService и 2 класса, реализующие этот интерфейс. А также у меня есть класс, у которого есть конструктор, получающий IService и int. Как я могу создать экземпляр этого класса с помощью Ninject (я бы не хотел, чтобы это было сложно, я хочу передавать его каждый раз, когда я получаю экземпляр)?Создание экземпляра с использованием Ninject с дополнительными параметрами в конструкторе

Вот код, иллюстрирующий ситуацию:

interface IService 
{ 
    void Func(); 
} 

class StandardService : IService 
{ 
    public void Func() 
    { 
     Console.WriteLine("Standard"); 
    } 
} 

class AlternativeService : IService 
{ 
    public void Func() 
    { 
     Console.WriteLine("Alternative"); 
    } 
} 


class MyClass 
{ 
    public MyClass(IService service, int i) 
    { 
     this.service = service; 
    } 

    public void Func() 
    { 
     service.Func(); 
    } 

    IService service = null; 
} 
class Program 
{ 
    static void Main(string[] args) 
    { 
     IKernel kernel = new StandardKernel(new InlineModule(
      x => x.Bind<IService>().To<AlternativeService>(), 
      x => x.Bind<MyClass>().ToSelf())); 

     IService service = kernel.Get<IService>(); 

     MyClass m = kernel.Get<MyClass>(); 
     m.Func(); 
    } 
} 

ответ

84

With.ConstructorArgument существовал в 1.0 для этой цели. В версии 2.0 синтаксис немного изменился: - With.Parameters.ConstructorArgument with ninject 2.0

См Inject value into injected dependency для более подробной информации и примеров того, как использовать контекст, провайдеры и аргументы, чтобы передать вещи, как это вокруг более правильно.

EDIT: Как Стивен избран притворяться мой комментарий не имеет никакого отношения, я бы лучше дать понять, что я говорю с некоторыми примерами (для 2.0):

MyClass m = kernel.Get<MyClass>(new ConstructorArgument("i", 2)); 

, который на моих глазах очень ясно и точно указывает, что происходит.

Если вы находитесь в позиции, где вы можете определить параметр в более глобальном плане вы можете зарегистрировать поставщика и сделать это так:

class MyClassProvider : SimpleProvider<MyClass> 
{ 
    protected override MyClass CreateInstance(IContext context) 
    { 
     return new MyClass(context.Kernel.Get<IService>(), CalculateINow()); 
    } 
} 

и зарегистрировать его, как это:

x => x.Bind<MyClass>().ToProvider(new MyClassProvider()) 

NB бит CalculateINow() бит, где вы ввели бы свою логику, как в первом ответе.

Или сделать его более сложным, как это:

class MyClassProviderCustom : SimpleProvider<MyClass> 
{ 
    readonly Func<int> _calculateINow; 
    public MyClassProviderCustom(Func<int> calculateINow) 
    { 
     _calculateINow = calculateINow; 
    } 

    protected override MyClass CreateInstance(IContext context) 
    { 
     return new MyClass(context.Kernel.Get<IService>(), _calculateINow()); 
    } 
} 

Что вы зарегистрировать как так:

x => x.Bind<MyClass>().ToProvider(new MyClassProviderCustom(() => new Random().Next(9))) 

UPDATE: Новые механизмы, которые демонстрируют гораздо более совершенные модели с меньшим шаблонный, чем выше , содержащиеся в расширении Ninject.Extensions.Factory, см.: https://github.com/ninject/ninject.extensions.factory/wiki

Как указывалось ранее, if you need to pass a different parameter each time and you have multiple levels in the dependency graph, you might need to do something like this.

Заключительное соображение состоит в том, что, поскольку вы не указали Using<Behavior>, это будет по умолчанию по умолчанию, как указано/по умолчанию в параметрах ядра (TransientBehavior в образце), которые могли бы оказать тот факт, что завод рассчитывает i «на лету» [например, если объект был кеширован]

Теперь, чтобы прояснить некоторые другие моменты в комментариях, которые FUDed и затушевываются. Некоторые важные вещи, чтобы рассмотреть об использовании DI, будь то Ninject или что-то еще, чтобы:

  1. Иметь как можно сделать с помощью инъекции конструктора, так что вам не нужно использовать контейнер определенные атрибуты и приемы.Там есть хорошая запись в блоге, которая называется Your IoC Container is Showing.

  2. Свести к минимуму код, идущий в контейнер и запрашивающий материал - в противном случае ваш код будет связан с a) конкретным контейнером (который может свести к минимуму CSL). B) способ, которым весь ваш проект выложен. Есть хорошие сообщения в блогах о том, что CSL не делает то, что, по вашему мнению, делает. Эта общая тема называется Service Location vs Dependency Injection. ОБНОВЛЕНИЕ: см. http://blog.ploeh.dk/2011/07/28/CompositionRoot.aspx для подробного и полного обоснования.

  3. Минимизировать использование статики и одиночек

  4. Не думайте, что есть только один [глобальный] контейнер и что это нормально, чтобы просто требовать его всякий раз, когда вам это нужно, как хороший глобальной переменной. Правильное использование нескольких модулей и Bind.ToProvider() дает вам структуру для управления этим. Таким образом, каждая отдельная подсистема может работать сама по себе, и вы не будете иметь компоненты низкого уровня привязки к компонентам верхнего уровня и т.д.

Если кто-то хочет, чтобы заполнить ссылки на блоги, я имею в виду к, я был бы признателен (все они уже связаны с другими сообщениями на SO, хотя, так что все это просто дублирование UI было введено с целью избежать путаницы в вводящем в заблуждение ответе.)

, если бы только Джоэл мог войти и действительно поставил меня прямо на хороший синтаксис и/или правильный способ сделать это!

UPDATE: В то время как этот ответ явно полезно из числа upvotes это набравшими, я хотел бы сделать следующие рекомендации:

  • выше чувствует, как это немного устаревшей и честно отражает много неполного мышления, которое почти чувствует себя смущенным после чтения. Dependency Injection in .net - Запустите и купите его сейчас - это не только о DI, первая половина - это полное обращение ко всем проблемам архитектуры, окружающим его от человека, который провел здесь слишком много времени, вися вокруг тега инъекции зависимостей.
  • Go чтения Mark Seemann's top rated posts here on SO right now - вы узнаете ценные методы от каждого
+0

Хорошо, чтобы найти это, поскольку документация так далеко позади .... – Elton

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

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