【问题标题】:Best Practice: How to get several dependency repositories into a ActionController?最佳实践:如何将多个依赖存储库放入 ActionController?
【发布时间】:2010-01-24 17:11:29
【问题描述】:

我有一个 InventoryController,它获取了一个 IInventoryRepository,但是我的需求发生了变化,现在其中一个控制器方法还需要使用另外 2 个存储库,ILoansRepository(查看有关借出库存项目的获取信息)和另一个,在哪里可以找到一些统计数据和额外信息。

它的工作方式是从 InventoryController 中的 ActionMethod 调用的 ViewModelBuilder 类,这是真正需要这些的类。目前我正在将 IInventoryRepository 从控制器传递给构建器,但是我现在应该怎么做呢?我是否应该像现在一样将 3 个存储库注入控制器,然后将它们传递给构建器?还是我应该只做一个 IoC.GetInstance()? (虽然我认为这是一种反模式不是吗?)

谢谢!

【问题讨论】:

    标签: c# asp.net-mvc dependency-injection ioc-container


    【解决方案1】:

    在这样的情况下,以下准则会发挥作用:

    • 过多的依赖项是一种违反Single Responsibility Principle 的气味。
    • 依赖项不超过四个。这是一个相对的指导方针。我个人努力减少;一旦添加第三个依赖项(请参阅上面的第一项),我就会变得焦躁不安,但最多可以忍受四个。不仅如此,我还必须重构。
    • 不要仅仅为了传递依赖而接受依赖。

    据我所知,对于三个依赖项,当涉及到依赖项的数量时,您仍然或多或少处于安全范围内,尽管您应该开始更仔细地观察特定的设计方面。

    但是,据我了解您当前的实现,您只需将依赖项传递给 ViewModelBuilder(因此违反了第三个项目符号)。一个更好的选择是定义一个抽象(比如,IViewModelBuilder)并将其注入控制器而不是所有三个存储库。

    在任何情况下,您都不应诉诸服务定位器反模式 (IoC.GetInstance())。

    【讨论】:

    • 听起来确实不错,虽然Controller本身也需要InventoryRepository来做CRUD,但或许通过IRepo+IViewModelBuilder...你觉得呢?
    • 您对制作 IViewModelBuilder 有何看法,然后让 Controller 接收(IInventoryRepository 存储库,IViewModelBuilder viewModelBuilder)并在我的 IoC 配置中有类似的内容:ForRequestedType>().TheDefaultIsConcreteType() 和目录视图模型构建器本身需要一个 InventoryRepo 和 LoansRepo 的实例,但是 IoC 也可以处理它,可以吗?感觉有点太复杂了!
    • 对我来说这听起来像是一个很好的重构。不是更复杂,只是不同,职责划分更清晰。这里唯一仍然不和谐的是,通过混合 IInventoryRepository 和 IViewModelBinder,您可以在同一个构造函数中混合一个“低级”服务(存储库)和一个“高级”服务。它暗示不对称,但它也一直发生在我身上。但是,当它发生时,我总是关注这种不对称,因为它暗示“低级”服务也可能被另一个“高级”服务取代。
    • :) 好吧,我想我会暂时保留它 :) 谢谢!
    【解决方案2】:

    对控制器负责。

    也许您应该创建一个特殊的服务来处理这个问题,并且该服务应该使用那些由构造函数自动连接的存储库(通过 IoC)。

    【讨论】:

      【解决方案3】:
      1. 如果你的控制器做的工作太多,把它分成几个。

      2. 如果您注入 3 个存储库只是为了创建 ViewModelBinder,请不要:改为注入 (I)ViewModelBinder。让 IoC 容器完成它的工作并为您解决依赖关系;此外,这将简化架构、测试等。

      3. 使用 ServiceLocator / GetInstance 并不总是可以避免的;有时您没有像 MVC 控制器工厂那样的“根”注入点,并且无法控制对象创建 - 例如,模型绑定器。所以,我让我的模型绑定器(不是构建器)调用 GetInstance,但我创建了自己的“根”:例如,它们调用 GetInstance,而不是 GetInstance

      【讨论】:

      • 谢谢,但我的意思是模型构建器而不是绑定器,它有点相反,绑定器将从请求中获取信息并将其绑定到对象,构建器将获得创建发送到视图的对象所需的所有信息,请查看这个很棒的博客:tiny.cc/michelottiMVC 问题是我真的不认为库存控制器做得太多,但它只需要这条信息它的一种方法(库存清单,因为它应该说明是否借出物品,并且那是在贷款库存中)或者我应该合并贷款和投资。回购?
      • 它目前是一个单独的回购,因为我需要有所有产品的所有贷款的历史,所有产品的当前贷款,过期的,一个产品的所有贷款(它的历史),贷款给特定的人,有逾期贷款的人等
      • 关于单独的repo,如果你需要3个repo来创建Builder,其中1个来获取数据,将1个repo和1个Builder注入控制器。不要自己从依赖项中创建对象。
      • 至于builder/binder,没关系;原理是一样的。您不会“将 3 个存储库注入控制器,然后将它们传递给构建器”——您注入客户端(控制器)需要的直接依赖项,而 IoC 容器会为您完成所有工作。它有很多后果,例如,如果需求发生变化,您不会更改创建模型构建器的 10 个位置;您只需更改 IoC 配置(实际上它是自动推断的)。它更容易测试,因为您模拟了 1 个具有必需功能的类,而不是 3 个具有可选方法的类......等等。
      猜你喜欢
      • 2010-12-11
      • 2016-04-04
      • 2015-09-21
      • 1970-01-01
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 2021-11-21
      相关资源
      最近更新 更多