我应该封装我的IoC容器吗?

时间:2009-11-19 02:04:28

标签: ioc-container encapsulation

我正在尝试决定是否有必要通过额外的努力来封装我的IoC容器。经验告诉我,我应该在我的应用程序和任何第三方组件之间放置一层封装。我只是不知道这是否接近矫枉过正。

我可以想到我可能想要切换容器的情况。例如,我目前的容器不再维护,或者证明不同的容器更轻,性能更好,更符合我的需要。如果发生这种情况,那么我可能需要进行大量的重新布线。

要明确的是,我正在考虑封装注册类型的解析。我认为封装解决方案是明智的 - 我希望通常的做法是将helper / util类委托给容器。

编辑:

我的假设是我更喜欢以编程方式为类型安全,编译时检查和可重构性连接我的类型。这是这个代码及其对我希望保护自己的容器的依赖。

我也一直在为其他几个共享很多相同关系的项目使用IoC容器,但容器很难处理,所以我想要改变。但是,更改意味着我失去了注册码的可重用性。因此,为什么我正在考虑封装。这不是一个巨大的负担,但我仍然喜欢减轻负担。

我期待:

  • 最大限度地减少容器/容器版本变更的影响
  • 在可能使用不同容器的项目中提供某种级别的类型注册一致性
  • 提供对我有意义的接口方法(RegisterSingleton< T,T>而不是RegisterType< T,T>(SomeLifetimeProvider) - 以Unity为例)。
  • 在条件/可扩展性要求改变时增加容器,例如在解决/注册期间添加更好的缓存,日志记录等。
  • 提供我自己的模型来注册类型映射。
    • 假设我想在程序集/程序包中创建一堆RegistrationHandler对象,因此我可以轻松地将注册职责分隔到多个类中,并自动拾取这些处理程序,而无需在其他地方更改代码。

我意识到这有点主观,所以优点/缺点可能会有所帮助

谢谢!

4 个答案:

答案 0 :(得分:7)

稍后再做,并且只有在您确实需要更改IOC容器时才会这样做。

选择一个非侵入性的IOC容器。也就是说,彼此连接的对象与IOC容器没有任何依赖关系。在这种情况下,没有什么可以封装的。

如果您必须选择一个要求您对容器有依赖关系的IOC容器,请选择一个具有最简单依赖关系/ API的容器。如果您需要替换此IOC容器(并且您可能不会),请实现将新API桥接到旧API的适配器。

换句话说,让第一个IOC容器成为为任何未来容器定义接口的容器,这样您就不必创建自己的容器,并且可以延迟任何此类容器工作,直到你绝对需要它。

编辑:

我认为没有一种方法可以保证类型安全性不足:

  1. 设计一个相对复杂的Builder模式实现,以及可以编写IOC配置文件或类似内容的访客实现。
  2. 实现类型安全的IOC配置DSL。 (我的选择是否有多个应用程序需要可交换的IOC容器。)

答案 1 :(得分:1)

是的,去吧。这不是一个额外的努力,就像你说的那样,它可以让你更好地隔离第三方组件。

这也意味着如果您发现更好的东西,您可以轻松切换IoC容器。我最近做了这个,换掉了Spring.net IoC容器的结构图。

Codeplex上的ASP.NET MVC Contrib项目是一个非常好的起点。这就是我的实施基础。

答案 2 :(得分:1)

最佳做法是只在有实际需要的情况下才能做某事,并且永远不会编码您认为将来有时需要的东西(这就是所谓的YAGNI - 原则)。如果您的架构没问题,您可以轻松更改容器,如果它实际上是必要的......

如果您认为需要这种灵活性,可以查看CodePlex上的Common Service Locator project。它完全符合您的要求:为各种IoC容器提供通用外观。

HTH!

答案 3 :(得分:1)

我更愿意隔离与IOC容器的交互轨迹,而不是封装IOC容器本身。例如,在ASP.Net MVC中,我通常将容器的暴露限制在控制器工厂和global.aspx.cs文件中,通常设置它。

在我看来,拥有大量了解IOC容器的代码是一种增加复杂性的反模式。我已经看到了相当多的代码,其中对象可以随意向IOC容器询问它们的依赖关系,然后它们基本上将IOC容器减少到高维护的服务定位器。

由于IOC容器可以将依赖关系解析到任意深度,因此很容易使控制器工厂成为负责控制容器反转的组件。每个控制器的构造函数实质上指定了它所需的服务/存储库/网关。

对于我的任何应用程序,交换IOC容器主要是重写配置容器的代码(指定绑定等)并挂钩控制器工厂。对于作为服务公开的应用程序,相同的基本思想应该是合理可管理的,但是根据运行时的约束,您可能必须使用setter注入而不是构造函数注入。