5

假设ApplicationSettings类是适用于我的应用程序的设置的通用存储库,例如 TimeoutPeriod、DefaultUnitOfMeasure、HistoryWindowSize 等...假设 MyClass 使用其中一个设置 - DefaultUnitOfMeasure。

我对正确使用控制容器反转的阅读 - 如果我在这方面错了请纠正我 - 是您在其构造函数中定义类的依赖关系:

public class MyClass {
  public MyClass(IDataSource ds, UnitOfMeasure default_uom) {...}
} 

然后用类似的方法调用实例化你的类

var mc = IoC.Container.Resolve<MyClass>();

其中IDataSource已被分配一个具体实现,而 default_uom 已被连接以从ApplicationSettings.DefaultUnitOfMeasure属性进行实例化。然而,我不得不怀疑,所有这些箍是否真的有必要跳过。我有什么麻烦我应该怎么做

public class MyClass {
  public MyClass(IDataSource ds) {
    UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
  }
} 

是的,我的许多课程最终都依赖于IoC.Container,但无论如何我的大多数课程都会有这种依赖。只要类是耦合的,我似乎应该充分利用它。请敏捷大师,告诉我我错在哪里。

4

4 回答 4

4

根据我的 IoC 容器,我通常没有很多课程。我通常尝试将 IoC 的东西包装在我注入其他类的外观对象中,但通常我的大部分 IoC 注入仅在我的应用程序的更高层中完成。

如果你按照自己的方式做事,那么如果不为测试创建 IoC 配置,就无法测试 MyClass。这将使您的测试更难维护。

另一个问题是您将拥有想要更改配置的软件高级用户编辑您的 IoC 配置文件。这是我想避免的。您可以将 IoC 配置拆分为普通配置文件和 IoC 特定内容。但是您也可以使用普通的 .Net 配置功能来读取配置。

于 2008-09-22T14:39:55.743 回答
4

IoC.Container.Resolve("default_uom");

我认为这是一个经典的反模式,您将 IoC 容器用作服务定位器 - 导致的关键问题是:

  • 如果您的容器配置错误,您的应用程序将不再快速失败(您只会在它第一次尝试在代码中解析该特定服务时才知道它,除了一组特定的逻辑/情况外,这可能不会发生)。
  • 更难测试 - 当然不是不可能,但是您要么必须为测试创建一个真实的(和半配置的)windsor 容器实例,要么使用 IWindsorContainer 的模拟注入单例 - 这给测试增加了很多摩擦,与仅能够通过构造函数/属性将模拟/存根服务直接传递到您的测试类相比。
  • 更难维护这种应用程序(配置不是集中在一个位置)
  • 违反许多其他软件开发原则(DRY、SOC 等)

您原始陈述的相关部分暗示您的大多数类将依赖于您的 IoC 单例 - 如果它们通过构造函数/依赖项注入所有服务,那么与 IoC 有一些紧密耦合应该是例外规则 - 通常我唯一依赖容器的时候是当我做一些棘手的事情时,即试图避免循环依赖问题,或者出于某种原因希望在运行时创建组件,即使这样我也可以通常避免依赖于通用 IServiceProvider 接口以外的任何东西,如果我需要在原始项目之外的环境中重用组件,则允许我交换自制 IoC 或服务定位器实现。

于 2008-09-23T03:26:33.623 回答
2

是的,我的许多课程最终都依赖于 IoC.Container,但无论如何我的大多数课程都会有这种依赖。

我认为这是问题的症结所在。如果实际上您的大多数类都与 IoC 容器本身耦合,那么您可能需要重新考虑您的设计。

一般来说,您的应用程序应该只在引导期间直接引用一次容器类。在您将第一个钩子连接到容器之后,对象图的其余部分应该完全由容器管理,并且所有这些对象都应该忘记它们是由 IoC 容器创建的事实。

于 2008-09-22T14:34:37.627 回答
2

要评论您的具体示例:

public class MyClass {
    public MyClass(IDataSource ds) {
        UnitOfMeasure duom = IoC.Container.Resolve<UnitOfMeasure>("default_uom");
    }
}

这使得重用你的类变得更加困难。更具体地说,它使得在您限制它的狭窄使用模式之外实例化您的类变得更加困难。这将表现出来的最常见的地方之一是在尝试测试您的课程时。如果可以将 UnitOfMeasure 直接传递给构造函数,则测试该类会容易得多。

此外,您为 UOM 实例选择的名称(“default_uom”)意味着可以覆盖该值,具体取决于类的使用情况。在这种情况下,您不希望像这样对构造函数中的值进行“硬编码”。

使用构造函数注入模式不会使您的类依赖于 IoC,恰恰相反,它让客户端可以选择是否使用 IoC。

于 2008-09-23T03:50:44.907 回答