有没有理由不使用我的IoC作为一般设置存储库?

时间:2008-09-22 14:08:23

标签: inversion-of-control

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

我正确使用Inversion of Control Containers - 如果我错了,请纠正我 - 是你在构造函数中定义类的依赖关系:

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 个答案:

答案 0 :(得分:4)

根据我的IoC容器,我通常没有很多类。我通常会尝试将IoC内容包装到我注入其他类的Facade对象中,通常我的大部分IoC注入只在我的应用程序的更高层中完成。

如果按自己的方式做事,则无法在不为测试创建IoC配置的情况下测试MyClass。这将使您的测试更难维护。

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

答案 1 :(得分:4)

  

IoC.Container.Resolve( “default_uom”);

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

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

你原始陈述的相关部分暗示你的大多数类都依赖于你的IoC单例 - 如果他们通过构造函数/依赖关系注入了所有服务,那么与IoC紧密耦合应该是规则的例外 - 一般来说,我唯一一次依赖容器是因为我正在做一些棘手的事情,即试图避免循环依赖问题,或者希望在运行时出于某种原因创建组件,甚至那么我经常可以避免依赖于通用的IServiceProvider接口,如果我需要在原始项目之外的环境中重用组件,那么允许我交换家庭烘焙IoC或服务定位器实现。

答案 2 :(得分:2)

  

是的,我的许多课程最终依赖于IoC.Container,但这是我的大多数课程依赖的依赖。

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

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

答案 3 :(得分:2)

评论您的具体示例:

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

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

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

使用构造函数注入模式不会使您的类依赖于IoC,恰恰相反,它为客户提供了使用IoC的选项。