小编Div*_*ium的帖子

使用IoC和依赖注入,如何在不违反Open-Closed原则的情况下用新的实现层包装代码?

我试图弄清楚如何在实践中做到这一点,以免违反开放封闭原则.

假设我有一个名为HttpFileDownloader的类,它有一个函数,它接受一个url并下载一个文件,将html作为字符串返回.这个类实现了一个只有一个函数的IFileDownloader接口.所以在我的代码中我都引用了IFileDownloader接口,每当IFileDownloader被解析时,我的IoC容器都会返回一个HttpFileDownloader实例.

然后在一些使用之后,很明显有时服务器当时太忙并且抛出异常.我决定绕过这个,如果我得到异常,我将自动重试3次,并在每次重试之间等待5秒.

所以我创建了HttpFileDownloaderRetrier,它有一个函数在for循环中使用HttpFileDownloader,最多3个循环,每个循环之间等待5秒.因此,我可以测试HttpFileDownloadRetrier的"重试"和"等待"能力我通过让HttpFileDownloaderRetrier构造函数采用IFileDownloader来注入HttpFileDownloader依赖项.

所以现在我希望所有解析IFileDownloader都返回HttpFileDownloaderRetrier.但是,如果我这样做,那么HttpFileDownloadRetrier的IFileDownloader依赖将获得自己的实例,而不是HttpFileDownloader.

所以我可以看到我可以为HttpFileDownloader创建一个名为IFileDownloaderNoRetry的新接口,并更改HttpFileDownloader来实现它.但这意味着我正在改变违反Open Closed的HttpFileDownloader.

或者我可以为HttpFileDownloaderRetrier实现一个名为IFileDownloaderRetrier的新接口,然后更改所有其他代码以引用它而不是IFileDownloader.但是,我现在在所有其他代码中违反Open Closed.

那我在这里错过了什么?如何在不更改现有代码的情况下用新的实现层(重试和等待)包装现有实现(下载)?

如果有帮助,这里有一些代码:

public interface IFileDownloader
{
  string Download(string url);
}

public class HttpFileDownloader : IFileDownloader
{
  public string Download(string url)
  {
    //Cut for brevity - downloads file here returns as string
    return html;
  }
}

public class HttpFileDownloaderRetrier : IFileDownloader
{
  IFileDownloader fileDownloader;

  public HttpFileDownloaderRetrier(IFileDownloader fileDownloader)
  {
    this.fileDownloader = fileDownloader;
  }

  public string Download(string url)
  {
    Exception lastException = null;
    //try 3 shots of pulling a bad URL.  And wait 5 …
Run Code Online (Sandbox Code Playgroud)

c# dependency-injection ioc-container open-closed-principle

7
推荐指数
1
解决办法
1066
查看次数