Создание новых экземпляров при использовании инъекции зависимостей - PullRequest
6 голосов
/ 02 августа 2011

Краткое описание среды:

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

Проблема

Вот соответствующий код, который я использую.

public interface IChatroomLogger
{
    void Log(ServerPacket packet);
    void Open();
    void Close();
}

public class ChatroomLogger : IChatroomLogger
{
    // chatroom name will be used as a file name
    public ChatroomLogger(string chatroomName) { ... }
    public void Log(ServerPacket packet) { ... }
}

public class Chatroom
{
    public Chatroom(string name, IChatroomLogger logger)
    {
        this.name = name;
        this.logger = logger;
        this.logger.Open();
    }

    public IChatromLogger Logger { get { return this.logger; } }
}

public interface IChatManager
{
    Chatroom Get(chatroomName);
}

Он используется в приложении следующим образом:

var room = ChatManager.Get(chatroomName);
romm.DoStuff();
room.Logger.LogPacket(receivedPacket);

ChatManager - это класс, который содержит ссылки на все чаты и отвечает за их создание и удаление.Я еще не написал, но это интерфейс, против которого я кодировал.

Вопрос

Как мне получить ChatManager для создания новых экземпляров Chatroom и по-прежнему использоватьвнедрение зависимостей ??

Я использую Unity, чтобы делать все мои другие вещи DI.Пока все работает отлично.Но я не уверен, как обойти эту загадку.

Когда моя конкретная реализация ChatManager создает новые чаты, она должна передать IChatroomLogger.Он не знает, как это построить ... но Unity знает.Но тогда я должен перейти в IUnityContainer в ChatManager.

public class ChatManager : IChatManager
{
    public ChatManager(IUnityContainer container)
    {
        this.container = container;
    }

    public Chat Get(string chatroomName)
    {
        // get logger from Unity somehow. Not sure how I'd 
        // pass chatroomName to the concrete instance
        var logger = ...
        return new Chatroom(chatroomName, logger);
    }
}

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

Как я могу получить новые экземпляры класса Chatroom, пока мое приложение находится в середине работы, не прибегая к какой-либо схеме поиска сервисов?Я обдумываю это?Разве это не большая проблема, чтобы обойти Unity?Любые мысли приветствуются!

Ответы [ 2 ]

4 голосов
/ 02 августа 2011

Ты прав.Такое использование IUnityContainer больше не использует внедрение зависимостей.Вместо этого он использует шаблон «Service Locator».В таких случаях я обычно создаю интерфейс IFactory<T>, например:

public IFactory<T>
{
    T Get();
}

Затем реализуем интерфейс с классом, о котором знает , и используем IUnityContainer.Настройте привязки так, чтобы IFactory<> запросов создавали экземпляр этого фабричного класса.Таким образом, вы можете добавить интерфейс IFactory<Logger> в ваш ChatManager и вызывать .Get() в любое время, когда вам нужен экземпляр регистратора.

1 голос
/ 02 августа 2011

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

  • Добавьте IChatroomProvider в свой дизайн с помощью метода Create (string roomname)
  • В ChatroomProvider используйте контейнер для создания именованных экземпляров (контейнер будет управлять жизненным циклом каждого именованного экземпляра, поэтому вам не нужно управлять словарем).
  • Зарегистрируйте ChatroomProvider с контейнером
  • Пусть ChatManager зависит от IChatroomProvider
  • Когда ChatManager нужен чат, он может просто задать свой IChatroomProvider
  • Использование контейнера для создания экземпляра ChatManager
  • Экземпляры регистратора будут создаваться при создании чатов
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...