Встраивание конструктора с помощью других аргументов конструктора

Я новичок в контейнерах 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 всегда имеет имя, мы требуем, чтобы он был передан конструктору.

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

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

Ответ 1

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

Ответ 2

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

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

    private string _name;

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

Реализация StaticKernelContainer может быть найдена в проекте NInject Web extensions.

Ответ 3

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

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