2009-11-06 3 views
10

Я новичок в контейнерах IOC, и я начинаю работу с NInject.Впрыск конструктора с другими, без зависимостей, аргументы конструктора

Что вы делаете, если хотите, чтобы ваш конструктор имел параметры, которые не являются службами, и не нужно создавать экземпляр контейнером IOC?

Например:

public class Person 
{ 
    private readonly string _name; 
    private readonly IPersonRepository _repository; 

    public Person(string name, IPersonRepository repository) 
    { 
     _name = name; 
     _repository = repository; 
    } 

    ...... 
} 

Представьте себе, что имя является требованием класса Person, так, чтобы гарантировать, что человек всегда имеет имя, мы требуем, чтобы он был принят в конструктор.

Как мы можем получить экземпляр Person с использованием NInject? Имя должно быть передано в зависимости от того, какой бит приложения создает новое лицо, в то время как контейнер IOC должен пройти в IPersonRepository.

Я понимаю, что либо имя, либо репозиторий можно было бы вводить с использованием свойства вместо этого, но это не было бы чистым решением - мы теряем семантическую силу языка программирования.

ответ

5

Класс, как указано выше, не будет хорошим кандидатом для использования с контейнером МОК. Вы смешиваете проблемы здесь с объектом Person, имеющим некоторое состояние (имя) и выполняющим какое-либо действие (независимо от того, какой репозиторий используется). Если вы реорганизуете свой код, чтобы объект Person был восстановлен или создан через класс, который выполняет реализацию IPersonRepository через конструктор, вы попадете в точку, где инъекция зависимостей имеет смысл.

+0

OK имеет смысл - я вижу, как это будет работать в моем коде – cbp

2

Я почтительно не согласен с ответом Кевина МакМэхона выше, и причина в том, что я видел код инъекции зависимостей, который делает именно то, что вы хотите ... только с другим контейнером IoC. А именно, это был замок Виндзор, который является другим контейнером Ioc. Это позволит вам создать раздел в вашем файле конфигурации, чтобы сказать, какие значения должны быть указаны для имени (не имеет большого смысла это делать для имени, но если бы это было свойство типа «connectionString», это могло бы сделать много смысл).

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

+1

На самом деле я думаю, что NInject может это сделать: например: http://stackoverflow.com/questions/1374098/with-parameters-constructorargument-with-ninject -2-0 Но нужно передать имена параметров в виде строк; не имея аргументов конструктора, видимых в Intellisense; long method name ('WithConstructorArguments') ... дайте мне перерыв! – cbp

8

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

public class Person 
{ 
    [Inject] 
    public IPersonRepository PersonRepository { get; set; } 

    private string _name; 

    public Person(string name) 
    { 
     _name = name; 
     StaticKernelContainer.Inject(this); 
    } 
} 

Реализация StaticKernelContainer можно найти в проекте веб-расширений Ninject.

+1

+1 для последующего действия – ChrisWue

+0

Связанный вопрос и другой ответ здесь: http://stackoverflow.com/questions/12136926/dependency-injection-with-constructor-parameters-that-arent-interfaces#comment16245407_12136926 –