Как DI фактически делает инъекцию в собственность? - PullRequest
1 голос
/ 24 июля 2010

Я искал свои мозги и не смог найти подходящий ответ, так что поехали! У меня есть следующее свойство в каждой из моих форм или объектов:

    private RootWorkItem m_RootWorkItem;
    [RootWorkItem(Inject = true)]
    public RootWorkItem RootWorkItem {

        get {
            if (m_RootWorkItem == null) {
                m_RootWorkItem = new RootWorkItem();
            }
            return m_RootWorkItem;
        }
    }

Обратите внимание, что RootWorkItem - это разработанный мной класс, содержащий коллекцию Services (Collection). В основном все мои сервисы загружаются из внешних DLL-файлов с использованием отражений и Activator.CreateInstance и помещаются в RootWorkItem.Services.

Но как на самом деле я могу "внедрить" самый первый RootWorkItem, созданный в каждый другой RootWorkItem, помеченный моим атрибутом в моей программе?

Как эти паттерны DI на самом деле "делают" инъекцию "в" свойство? Я знаю концепции DI, но я пытаюсь написать свой собственный, очень базовый DI только для одного объекта. Я возился с тоннами размышлений, пытаясь найти подходящий способ сделать это, и я даже не готов придумать правильный способ сделать это.

Отредактировано для более ясного вопроса: Как структура / служба DI узнает, когда создается объект, который содержит свойство для внедрения?

е:

    class MyForm : Form {
        [RootWorkItem(Inject = true)]
        public RootWorkItem RootWorkItem { get; set; }
    end class

    class Program {
        Main {
            MyForm form = new MyForm();
            form.Show();
        }
    end class

Как он узнает, что при создании формы внедряется значение свойства, если ничто не уведомляет службу о том, что она была создана или ее нужно внедрить?

Ответы [ 2 ]

5 голосов
/ 24 июля 2010

Вы задаете правильный вопрос: «Как он узнает, что нужно ввести значение свойства при создании формы, если ничто не уведомляет службу о том, что она была создана или ее нужно внедрить?»

Вы 'Также правильно, когда вы говорите: «Если ничто не уведомляет службу о том, что она была создана, или она нуждается во внедрении», то инфраструктура DI не может выполнить свою работу.потому что вы используете инфраструктуру DI для создания объекта, которому вводятся его зависимости.В этом случае вы используете платформу DI для создания вашей формы, поэтому она знает об объекте и может внедрять зависимости.

Вместо

MyForm form = new MyForm(); 
form.Show();

Do

MyForm form = DIFramework.CreateForm(typeof(MyForm));
form.Show();

Теперь ваша структура DI знает об объекте!

По сути, new является врагом DI, поскольку это означает, что вызывающая сторона контролирует построение объекта.Вместо этого вызывающий должен передать эту ответственность кому-то другому, то есть структуре DI.Вызывающая сторона должна только когда-либо просить инфраструктуру DI предоставить / построить / настроить объекты.

1 голос
/ 24 июля 2010

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

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

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        if (m_RootWorkItem == null) {
            m_RootWorkItem = new RootWorkItem();
        }
        return m_RootWorkItem;
    }
}

Возможно ли, что ваше замешательство связано с размещением атрибута?

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

[RootWorkItem(Inject = true)]
private RootWorkItem m_RootWorkItem;
public RootWorkItem RootWorkItem {

    get {
        return m_RootWorkItem;
    }
}

Таким образом, вы можете пойти еще дальше и использовать автоматически реализованное свойство:

[RootWorkItem(Inject = true)]
public RootWorkItem RootWorkItem { get; private set; }

Наконец, я не уверен, почему тип атрибута совпадает с типом свойства и именем. Тогда я бы ожидал чего-то большего:

[Inject(true)]
public RootWorkItem RootWorkItem { get; private set; }

Я не знаю, какую платформу вы используете, поэтому я не могу комментировать, что делает параметр true, поэтому я включил его дословно.

отредактировано в связи с редактируемым вопросом

Вам не хватает понятия, что структура внедрения зависимостей также является абстрактной фабрикой.

Таким образом, вы не будете напрямую создавать экземпляр MyForm. Вместо этого вы должны каким-то образом зарегистрировать в своем DI-контейнере тип MyForm, а затем использовать контейнер для создания экземпляров для вас. Затем он создаст экземпляр, но перед возвратом вам он внедрит зависимости (которые он обнаруживает посредством отражения в атрибутах).

Например:

// configure at start-up
container.Register<MyForm>();

// some point later in your code
MyForm mf = container.Resolve<MyForm>();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...