依赖注入的初学者

时间:2014-11-12 15:15:01

标签: c# dependency-injection

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

问题是保存到磁盘需要一条路径,同时“保存”#39;因为电子邮件需要其他详细信息(从,到等)。

这是通过依赖注入可以实现的吗?或者我做错了什么?检查下面的代码和我的评论,以便更好地理解我的问题...

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

2 个答案:

答案 0 :(得分:2)

你需要做的就是通过足够的&#39;有关持久化类消息的上下文信息。然而,传递特定于电子邮件的信息(如从和到)会导致您将持久性机制的实现细节泄露到OriginalClass,这不是您应该要的。执行此操作将导致您每次添加新OriginalClass实施时都必须更改IPersistence。这显然很糟糕(它会打破OCPDIP)。

那么究竟要提供什么才是您可以确定的东西,但它可能是允许实现检索所需信息以进行操作的标识符。这可能类似于联系人或组织的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

答案 1 :(得分: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;
    }
}