【问题标题】:Dependency Injection and other constructor parameters - bad practice?依赖注入和其他构造函数参数 - 不好的做法?
【发布时间】:2013-04-29 23:38:09
【问题描述】:

目前我正在尝试使用依赖注入容器,这次是使用 Unity。

给定如下界面:

public interface IPodcastCommService
{
    void Download();

    void Upload();
}

以及以下实现:

public class PodcastService
{
     private IPodcastCommService commservice;
     private String url;

     public PodcastService(String url, IPodcastCommService commservice)
     {
         this.commservice = commservice;
         this.url = url;
     }
}

因为构造函数的关系,一直在找办法传参数给它,结果找到了:

var p = container.Resolve<IPodcastCommService>(new ParameterOverride("url", myUrl));

到目前为止一切都很好,但同时我读到这有多糟糕以及类的设计有多糟糕,是的,它看起来有点难看。但是如何以优雅的方式将参数传递给类?

我的第一个想法是把它作为一个属性来做,但是每次我需要它已经给出的 URL 时我都必须检查它。

更新: 一个例子,我读到这是一个糟糕的设计,是这样的:

但在某些情况下,您可能会为解析操作传入自定义构造函数参数。有些人可能会争辩说,这是糟糕架构的尖叫声,但在某些情况下,例如将 DI 容器引入遗留系统可能需要这些操作。

来源:http://mikaelkoskinen.net/unity-passing-constructor-parameters-to-resolve/

【问题讨论】:

  • 你介意告诉我你在哪里有红色这是糟糕的设计吗?因为我实际上认为这个设计是你能得到的最好的。
  • @Egi:我用来源更新了我的问题。
  • 您可以使用ServiceLocator 进行DI,而无需在构造函数中列出注入的属性。

标签: c# dependency-injection


【解决方案1】:

我不明白为什么你需要由IPodcastCommService 组成的PodcastService,而不是实现IPodcastCommService 并通过字符串注入url。我不明白你的设计为什么不好。注入网址是好的恕我直言。

如果您想到更好的方法,我认为可以通过注入上下文/配置而不是原生数据类型来替换它。

public class PodcastService
{
     private IPodcastCommService commservice;
     private IConnectionContext connection;

     public PodcastService(IConnectionContext connection, IPodcastCommService commservice)
     {
         this.commservice = commservice;
         this.connection= connection;
     }
}

public interface IConnectionContext{
    string PodcastServiceUrl{get;}
}

但同样,我没有从常规方法中找到任何好处(除了您可以处理会话/常量/静态字段)。

更新:

我发现了关于糟糕设计here 的类似问题。总之,并不是原生类型参数(字符串等)或自定义构造函数参数不好。只是您需要将参数放入真正负责该参数的类中。如果您在抽象工厂模式中处理 if-else 条件,则需要自定义构造函数参数。

【讨论】:

    【解决方案2】:

    也许是

    container.RegisterType<PodcastService>(new InjectionConstructor("myUrlParameter"));
    

    会更好,不是吗?

    但如果您需要不止一个播客服务并且他们需要另一个 url,我猜 parameteroverride 是可以的。

    【讨论】:

      【解决方案3】:

      在您的场景中,我认为通过构造函数进行 DI 非常好。它被认为是通过属性的更好方法的原因是因为它更好的可读性,即想象如果您必须注入 20 个属性,您的构造函数会是什么样子。

      如果您只打算注入几个属性,那么做您正在做的事情绝对没有害处。如果你发现你的依赖开始蔓延,我会考虑转向属性类型的方法。

      【讨论】:

      • 如果有多个注入,您可以使用Builder 模式来简化可读性。如果对象需要在使用之前设置属性,我认为这比使用属性要好得多。
      • 如果你的构造函数有 20 个参数,我敢打赌你的类违反了 SRP 并且应该被重构为更小的类而不是滥用属性注入以获得更好的可读性!如果您需要能够在运行时更改的动态行为,我认为属性注入很好。
      【解决方案4】:

      这取决于你使用的框架。例如 DependecyResolver 等 IoC 容器的 asp.net mvc 提供程序集成点。您应该将所有用于构造对象和注入依赖项的逻辑放在那里。如果您使用的是 aps.net,您可能有某种 preinit eevnt 注入依赖项的基本页面。您不能在 asp.net 中使用构造函数注入,只能使用属性注入。使用 winforms,您可以使用某种表单工厂来构建表单对象。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-04-12
        • 2011-02-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-20
        • 1970-01-01
        相关资源
        最近更新 更多