Краткий вопрос о Microsoft Unity IoC - PullRequest
0 голосов
/ 16 сентября 2011

В данный момент я просто пытаюсь обернуть голову вокруг IoC, и я часть пути туда Пример, который я нашел в другом посте на SO, был такой:

http://blog.vascooliveira.com/unity-tutorial-and-examples/

Строка, которую я не совсем понимаю, такова:

ILogger myExampleInstance = myContainer.Resolve(loggerType);

Я не уверен, что такое loggerType, поскольку он нигде не упоминает.

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

Я на полпути к пониманию этого, но мне просто нужен последний толчок! =)

Ответы [ 3 ]

5 голосов
/ 16 сентября 2011

То, что вы видите, на самом деле является анти-паттерном Service Locator . Пример кода напрямую ссылается на контейнер, вызывая его метод Resolve ().

В 99% случаев вам никогда не следует ссылаться на ваш контейнер в вашем коде - должна быть только одна ссылка на контейнер в приложении на самом высоком уровне вашего кода. (последние 1% случаев почти исключительно связаны с тем, что используемая вами среда не позволяет внедрять зависимости)

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

Есть много постов в блоге (вот два, которые я нашел с некоторым быстрым поиском в Google: Не ссылаться на Контейнер IoC и Сервисный локатор - это антишаблон вокруг объяснения различных причины плохого ServiceLocator.

Вы нашли один пример с вашим вопросом о том, каким должен быть loggerType, при использовании надлежащего IoC ваше приложение не должно заботиться - подход Service Locator обычно означает, что ваше приложение снова начинает осознавать детали своих зависимостей, что противоречит весь смысл использования IoC и внедрения зависимостей в первую очередь.

Для дальнейшего чтения по IoC я бы предложил просмотреть посты в блоге Джереми Миллера, создателя StructureMap . Не принимайте это, как я сказал, используйте StructureMap вместо Unity, но, поскольку он написал контейнер с нуля, большая часть того, что он говорит по этому вопросу, хорошо продумана, и он хороший писатель.

3 голосов
/ 16 сентября 2011

Было бы что-то вроде этого

public class MyLogger : ILogger
{
    //implementation
}

А потом

Type loggerType = typeof(MyLogger);

ILogger myExampleInstance = myContainer.Resolve(loggerType);
output = myExampleInstance.MyInterfaceMethod("Unity rocks!");

Проблема в том, что на самом деле это шаблон ServiceLocator .DI и IoC будут выглядеть так:

public class Foo
{
    private ILogger logger;

    //This will be injected automatically by IoC
    //once you register it somewhere in the app init e.g.
    //container.RegisterType<ILogger, MyLogger>();
    public Foo(ILogger logger)
    {
        this.logger = logger;
    }

    public void Bar()
    {
        logger.Debug("In the bar");
    }   
}
1 голос
/ 16 сентября 2011

Хотя ответ Дэвида Холла является более правильным, просто чтобы ответить на ваш вопрос, loggerType - это Type регистратора. В действительности они, вероятно, могли бы сделать:

ILogger myExampleInstance = myContainer.Resolve(typeof(ILogger));

Или, что еще лучше, используйте общий метод расширения:

var myExampleInstance = myContainer.Resolve<ILogger>();

Контейнер Unity рассмотрит список известных отображений и увидит, какой тип сопоставлен с ILogger. Затем он создаст новый экземпляр и вернет его.

В качестве более краткого примера:

IContainer container = ...;// get or create Unity container
container.RegisterType<ILogger, MyLogger>(); // tell Unity that when I ask for ILogger, I want a MyLogger back
ILogger logger = container.Resolve<ILogger>(); // logger is set to a new instance of MyLogger

Надеюсь, это поможет!

...