依赖注入的初学者

本文关键字:初学者 注入 依赖 | 更新日期: 2023-09-27 18:30:12

所以我们有一个类,它确实需要输出操作的结果。现在这与电子邮件紧密耦合,但是通过依赖注入,我认为我可以添加更多的持久性选项,例如。保存到磁盘。

问题是保存到磁盘需要路径,而"保存"为电子邮件需要其他详细信息(发件人、收件人等(。

这是可以通过依赖注入来实现的吗?还是我做错了整件事?检查下面的代码和我的评论,以更好地了解我的问题......

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;
    }
}

依赖注入的初学者

您需要做的是将有关消息的"恰到好处"的上下文信息传递给持久性类。 传递特定于电子邮件的信息(例如 from 和 to(会导致您将持久性机制的实现细节泄漏到 OriginalClass 中,这不是您想要的。这样做会导致每次添加新的IPersistence实现时都必须更改OriginalClass。这显然是不好的(它破坏了OCP和DIP(。

因此,究竟要提供什么只有您可以确定,但它可能是允许实现检索运行所需信息的标识符。这可以类似于为其写入消息的联系人或组织的 ID。这样,您只需传入消息和此 ID,实现就可以使用此 ID 来查询数据库以获取所需的任何内容。

但是,如果这些值在应用程序运行时期间未更改,则解决方案将完全不同。在这种情况下,您应该简单地使用构造函数注入:

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

这样的东西应该可以工作,因为现在IEmailManager也可以通过DI框架,您需要做的就是引导EmailManager Construction。

   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;
    }
}