Начинающий по внедрению зависимости

1

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

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

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

public class OriginalClass
{
    IPersistence _persistence;

    public OriginalClass(IPersistence persistence)
    {
        this._persistence = persistence;
    }

    public void DoSomething()
    {
        // I have all the information needed to send an email / save to disk. But how do I supply it?
        this._persistence.Put("Message to save");
    }
}

public interface IPersistence
{
    bool Put<T>(T data);
}

public class EmailPersistence : IPersistence
{
    public bool Put<T>(T data)
    {
        // How am I going to get the FROM and TO details?
        return EmailManager.Send("FROM", "TO", data.ToString());
    };
}

public class DiskPersistence : IPersistence
{
    public bool Put<T>(T data)
    {
        // How am I going to get the SAVE PATH details?
        // I just used a new initialization. So I'm probably doing this wrong as well...
        new System.IO.StreamWriter("SAVE PATH").Write(data.ToString());

        return true;
    }
}
  • 1
    Всякий раз, когда вам нужен параметр времени выполнения для создания объекта, вам нужна абстрактная фабрика, см. Stackoverflow.com/questions/1943576/…
  • 0
    Почему вы используете универсальный T внутри вашей конкретной реализации вместо конкретного типа?
Показать ещё 14 комментариев
Теги:
dependency-injection

2 ответа

2

Что вам нужно сделать, так это передать "достаточно" контекстуальную информацию о сообщении классу persistence. Передача информации, связанной с электронной почтой, например, от и, тем не менее, приводит к утечке данных о реализации механизма персистентности в OriginalClass, что вам не нужно. Делать это заставит вас должны изменить OriginalClass каждый раз при добавлении нового IPersistence реализации. Это, очевидно, плохо (он разбивает как OCP, так и DIP).

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

Однако, если эти значения не изменяются во время выполнения приложения, решение полностью отличается. В этом случае вы должны просто использовать конструктор инъекции:

public class EmailPersistence : IPersistence {
    private readonly MailAddress from;
    private readonly MailAddress to;
    public EmailPersistence(MailAddress from, MailAddress to) {
        this.from = from;
        this.to = to;
    }

    public bool Put(string data) {
        // How am I going to get the FROM and TO details?
        return EmailManager.Send(this.from, this.to, data.ToString());
    };
}

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

  • 0
    Спасибо за подробный ответ. К сожалению, я не могу использовать предоставленный вами пример кода, так как FROM, TO / SAVE PATH - это детали, которые меняются во время выполнения приложения. Я думал о том, что вы упомянули об удостоверении личности. Но, сделав это, я бы не стал ограничивать классы постоянства тем, что их можно было использовать только тогда, когда контактное лицо доступно. И кроме того, не нарушил ли бы я принцип единой ответственности, если бы я установил классы постоянства для получения контактного лица по идентификатору, а затем для извлечения его деталей, если все, что ему действительно нужно, это ОТ, ТО / СОХРАНИТЬ ПУТЬ?
  • 0
    @ZuiqPazu: Вам не нужно нарушать SRP, выполняя то, что я предлагал, это просто вопрос отделения специфичных для человека вещей от очень общего персистентного материала, так что ваш OriginalClass может зависеть от IContactPersonRelatedPersistar или чего-то подобного.
0

Что-то вроде этого должно работать, так как теперь IEmailManager также может проходить через инфраструктуру DI, все, что вам нужно сделать, - это загрузить конструкцию EmailManager.

   public class OriginalClass
{
    IPersistence _persistence;

    public OriginalClass(IPersistence persistence)
    {
        this._persistence = persistence;
    }

    public void DoSomething()
    {
        // I have all the information needed to send an email / save to disk. But how do I supply it?
        this._persistence.Put("Message to save");
    }
}

public interface IPersistence
{
    bool Put<T>(T data);
}

public class EmailPersistence : IPersistence
{
    private readonly IEmailManager _manager;

    public EmailPersistence(IEmailManager manager)
    {
        _manager = manager;
    }

    public bool Put<T>(T data)
    {
        // How am I going to get the FROM and TO details?
        return _manager.Send();
    }
}

public class EmailManager : IEmailManager
{
    public string From { get; set; }
    public string To { get; set; }


    public bool Send()
    {
        throw new NotImplementedException();
    }


    public dynamic Data { get; set; }

}

public interface IEmailManager
{
    string From { get; set; }
    string To { get; set; }

    dynamic Data { get; set; }
    bool Send();
}

public class DiskPersistence : IPersistence
{
    public string Path { get; set; }

    public DiskPersistence(string path)
    {
        Path = path;
    }

    public bool Put<T>(T data)
    {
        // How am I going to get the SAVE PATH details?
        // I just used a new initialization. So I'm probably doing this wrong as well...
        new System.IO.StreamWriter(Path).Write(data.ToString());

        return true;
    }
}
  • 0
    DiskPersistence можно настроить, как вы предложили. Однако EmailPersistence имеет другое TO (и, возможно, FROM), и мне не очень нравится постоянно менять свойство IEmailManager. Любые другие предложения?
  • 0
    Извините, приятель, не совсем понял, что вы спросили в приведенном выше комментарии

Ещё вопросы

Сообщество Overcoder
Наверх
Меню