Таким образом, у нас есть класс, который действительно должен выводить результат операции. Теперь это было тесно связано с электронными сообщениями, однако с инъекцией зависимостей я думал, что могу добавить больше параметров сохранения, например. сохранить на диск.
Проблема в том, что для сохранения на диск требуется путь, а для "сохранения" по электронной почте требуются другие данные (от, до и т.д.).
Это что-то, что может быть достигнуто путем инъекции зависимостей? Или я все делаю неправильно? Проверьте код ниже и мои комментарии, чтобы лучше понять мою проблему...
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;
}
}
Что вам нужно сделать, так это передать "достаточно" контекстуальную информацию о сообщении классу 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
используя эти фиксированные значения конфигурации.
OriginalClass
может зависеть от IContactPersonRelatedPersistar
или чего-то подобного.
Что-то вроде этого должно работать, так как теперь 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;
}
}
T
внутри вашей конкретной реализации вместо конкретного типа?