【问题标题】:Why is IDependencyResolver tightly coupled with System.Web?为什么 IDependencyResolver 与 System.Web 紧密耦合?
【发布时间】:2017-07-13 12:21:07
【问题描述】:

为什么IDependencyResolver 与.NET 框架中的System.Web 程序集(MvcHttp)耦合?

DI 系统的目标不是应该提供一种不可知的方式来为客户提供依赖关系吗?如果我想在一个项目中使用IDependencyResolver,该项目不应引用与 System.Web 相关的任何内容,该怎么办?

编辑:
这更像是一个哲学问题,而不是关于如何做的请求,因为我知道还有其他替代方案,例如开源 DI 库。

【问题讨论】:

  • 它是一个接口,它说它不是紧密耦合的。您可以使用.net 中提供的内置依赖解析器,也可以通过实现IDependencyResolver 接口来编写自己的。如果您使用城堡 Windsor 或 Unity 或 Ninject,它们已经拥有自己的此解析器版本。
  • 有一个 IServiceProvider 接口是系统的一部分。但是,它是一个非常有限的界面

标签: c# asp.net .net asp.net-mvc asp.net-web-api


【解决方案1】:

DI 系统的目标不是应该提供一种不可知的方式来为客户提供依赖关系吗?

没错,但在这种情况下,IDependencyResolver 特定于定义它的库。正是该库的 DI 抽象允许一个不可知的可扩展点来解决依赖关系。我相信这是抽象的最初目标。

它并没有真正被其他库独立重用,这很明显MVCWeb API 都有两个版本。尽管它们具有相同的名称和相同的目的,但它们的实现方式略有不同。

它还演示了 Mark Seemann 在这篇文章中提到的 Conforming Container 反模式,该文章还提到了上述抽象作为 .NET 的符合容器的已知示例。甚至我使用IServiceProvider 的首选方法也列在了列表中。

如果我想在一个项目中使用IDependencyResolver 应该怎么办? 不引用与 System.Web 相关的任何内容?

我的建议是不要使用 System.Web 中的IDependencyResolver。我还要补充一点,最重要的是,应该特别注意遵循正确的设计模式,确保理解这些概念以及应该在哪里应用或避免它们。

【讨论】:

  • 很好的答案,但我仍然想知道为什么IServiceProvider 没有在System.Web 中重用,而不是IDependencyResolver
  • 这是该系统设计者的问题。然而,他们在下面的版本中恢复到IServiceProvider,这就是我们今天在asp.net-core中所拥有的。那是为了消除困扰 System.Web 的紧密耦合。
  • @Nkosi 我同意,拥有适当的组合根可以抵消不利因素。不能使用特定的容器功能是一个缺点,应该仔细权衡是否能够轻松更换容器。就个人而言,我从来不需要换掉一个容器。但我知道其他人不得不这样做。问题当然是更昂贵的:维护一个可能使用的抽象或在需要更改时硬着头皮。我个人关注 YAGNI。
  • @BatteryBackupUnit 我将看看如何将我们讨论的内容纳入答案。再次感谢您引起我的注意。
【解决方案2】:

接口IDependencyResolver 是System.Web 框架的扩展点。框架依赖此接口来解析(控制器等的)实例及其依赖关系。

框架有自己的接口实现,但您可以提供自己的接口实现。内置实现的功能有限(外部配置、注入类型、拦截)。

大多数 IOC-Container 和 DI-Frameworks 都提供了该接口的实现,以便您可以将它们集成到现有框架中。

【讨论】:

    【解决方案3】:

    为什么是 IDependencyResolver 与 .NET 框架中的 System.Web 程序集(Mvc 或 Http)?

    因为它是“他们”用来解析框架服务的接口。但是,是的……他们至少应该使用来自System 命名空间的IServiceProvider

    DI 系统的目标不是它应该提供一种不可知的方式 向客户提供依赖项 ?

    不。在这种情况下,这不是目标。框架作者的主要目标是让您扩展甚至替换框架正在使用的内部服务。

    在您的代码中,您应该在这些“标准”接口上引入您自己的外观。它们是非常弱的抽象——有利于基础,但与任何更丰富的解析或生命周期管理策略相去甚远。

    如果我想在不应该的项目中使用 IDependencyResolver 怎么办? 引用与 System.Web 相关的任何内容?

    你不能(不添加System.Web 参考)而且你不应该。在 DI 框架上使用您自己的内部抽象(外观)。就像您不应该在类中直接使用 NLog.ILogger 一样,同样适用于 DI 框架抽象。

    有些框架会使其接近或无法做到,但您应该尽可能使用自己的 Facades。

    同样的规则也适用于更广泛的意义。 不要(不必要地)将您的项目附加到某些云服务,例如 Azure。另一边有一天可能会有更好的价格。尽可能限制依赖性和粘性部分。

    编辑: 这更像是一个哲学问题,而不是关于如何做的要求, 因为我知道还有其他替代方案,例如开源 DI 库。

    哦...同样的建议也适用于 DI 框架。不要过度使用可以通过 Facade 以不同方式轻松实现的 DI 框架功能。

    注意:CI 管道、服务总线/消息队列框架也是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-05-24
      • 2014-02-04
      • 2014-10-03
      • 2018-11-19
      • 2017-12-28
      • 2012-08-28
      • 2013-12-25
      • 1970-01-01
      相关资源
      最近更新 更多