Контейнеры внедрения зависимостей: как обращаться с объектами, которые ни от чего не зависят? - PullRequest
2 голосов
/ 26 августа 2010

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

Однако иногда есть объекты, которые не зависят от чего-либо еще, но мы хотим, чтобы они были в графе объектов.Например, у меня может быть класс Notifier с событием Bazinga, и этот класс BazingaConsoleLogger:

public class BazingaConsoleLogger
{
    private readonly Notifier notifier;

    public BazingaConsoleLogger(Notifier notifier)
    {
        this.notifier = notifier;
        this.notifier.Bazinga += HandleBazinga;
    }

    private void HandleBazinga(object sender, EventArgs args)
    {
        Console.WriteLine("Bazinga!");
    }
}

Поскольку BazingaConsoleLogger не является зависимостью от чего-либо, он не будет созданконтейнером для инъекций зависимости.Каков наилучший способ исправить это?

Ответы [ 3 ]

5 голосов
/ 26 августа 2010

Если BazingaConsoleLogger является службой и не зависит от чего-либо, то он не используется нигде в вашей программе, поэтому класс можно удалить. Меньше кода FTW! : -)

Я не думаю, что это то, что вы на самом деле имеете в виду, так что вы можете объяснить, как вы в настоящее время используете BazingaConsoleLogger? Если вы фактически используете BazingaConsoleLogger, у вас уже есть зависимость (явная или нет) от BazingaConsoleLogger.

РЕДАКТИРОВАТЬ: чтобы свободно связывать события, я использую Windsor's Event Wiring . Если в вашем контейнере нет ничего подобного, его не должно быть трудно кодировать, вот общие принципы .

3 голосов
/ 27 августа 2010

В Виндзоре вы могли взломать что-то вроде этого:

container.Register(
   Component.For<Notifier>()
      .OnCreate((kernel, notifier) => 
         notifier.Bazinga += kernel.Resolve<BazingaConsoleLogger>().HandleBazinga)
);

однако я согласен с Маурисио Шеффером, и я бы отнесся к этому как к запаху и переосмыслил ваш дизайн в этом случае.

0 голосов
/ 13 марта 2011

A IListener интерфейс маркера может быть добавлен к классу. В коде запуска приложения я мог затем извлечь все экземпляры IListener из контейнера в дополнение к основному экземпляру программы:

container.Resolve<IEnumerable<IListener>>(); // just to create the listeners
var program = container.Resolve<Program>();
program.Run();

Другой вариант заключается в использовании интерфейса IStartable (, созданного с помощью Autofac ), который решает более общую проблему, то есть запуск нескольких служб при запуске. В случае класса прослушивателя событий метод Start может использоваться для подписки на событие (таким образом снимая эту ответственность с конструктора) или просто ничего не делать. Класс Program может быть одной из реализаций IStartable.

var startables = container.Resolve<IEnumerable<IStartable>>();
foreach (var startable in startables)
{
    startable.Start();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...