【问题标题】:Can inversion of control and RAII play together?控制反转和RAII可以一起玩吗?
【发布时间】:2009-10-10 15:59:13
【问题描述】:

我刚刚阅读了控制反转 (IOC) 的内容,这让我很困扰,它似乎让内存管理变得很痛苦。当然,看起来 ioc 主要用于垃圾收集环境(Net、Java、脚本),而我关心的是非 gc 设置。

我担心的是 IOC 在某种程度上违背了 RAII,因为我们将资源生命周期与对象生命周期分离。这种增加的复杂性不会打扰其他人吗?而真正的问题是,什么技术可以用来让事情顺利进行?

【问题讨论】:

标签: inversion-of-control raii


【解决方案1】:

出于这个原因,我制作了自己的 IoC 容器,该容器返回(在 C#/.NET 中)一次性服务包装器,当被处理掉时,将在服务方面“做正确的事情”。

就这样吧:

  • 什么都不做,当:
    • 对象未实现 IDisposable
    • 不是容器范围的(在这种情况下,容器会跟踪它并多次返回同一个对象,当容器被释放时,对象也会被释放)
    • 未合并
    • 它不是单例范围的(与容器范围相同,但容器的层次结构会将单例范围的服务存储在最顶层的容器中)
  • Dispose 服务(它具有工厂范围,并实现 IDisposable)
  • 把它放回游泳池

这意味着使用我的服务的所有代码都在 using-block 中,但意图更清楚,至少对我而言:

using (var service = container.Resolve<ISomeService>())
{
    service.Instance.SomeMethod();
}

基本上它是这样说的:解析一个服务,在服务实例上调用 SomeMethod,然后处置该服务。

由于消费者不知道是否处置服务实例,因此要么完全忽略 IDisposable 实现,要么处置所有实现 IDisposable 的服务。这对我来说都不是一个好的解决方案。第三种选择是将服务实例包装在一个对象中,该对象知道一旦包装器被丢弃,该服务将如何处理。

【讨论】:

  • 有时鸭式输入 IDisposable 最终是不可避免的(例如在实现可用 GetEnumerator() 方法但未实现 IEnumerable&lt;T&gt; 的类型上使用 foreach 时),但这是一个主要的闻起来,因为当你注意到一个类持有对实现 IDisposable 的东西的引用这一事实并不总是意味着它“拥有”由此引用的对象。
【解决方案2】:

是和不是。 IoC 不会将资源生命周期与对象生命周期解耦,它将方法调用范围与对象生命周期解耦——您通常希望在方法结束时被销毁的对象存在,直到进行另一个 IoC 调用。因此,您要么必须将方法的局部变量移动到类范围中,并确保没有方法是可重入的,要么采用另一种方法,例如传递一个额外的“环境”以允许对象归其所有并销毁在随后的 IoC 方法调用中。如果你想要一个通用的事件驱动系统,这两种方法都会变得相当复杂——要么你的模型最终不得不自己实现显式递归和迭代,要么你的简单 RAII C++ 代码迅速变成了一个非常复杂的回调嵌套——足够复杂以至于我放弃了在 C++ 和 RAII 上开始使用 kin。

【讨论】:

    【解决方案3】:

    我首先想到的是智能指针。和模板参数。但我不确定模板参数是否算作 IOC 技术,尽管我认为它们应该。 至少这些可以缓解 IOC 的一些问题,但并不是完全赞同这个想法。

    【讨论】:

      猜你喜欢
      • 2015-06-30
      • 2012-02-06
      • 2015-07-03
      • 1970-01-01
      • 2020-06-17
      • 1970-01-01
      • 2016-05-21
      • 2015-02-21
      • 1970-01-01
      相关资源
      最近更新 更多