通过依赖注入,一个班级'依赖项由调用者实例化并传入,通常作为构造函数参数。这适用于具有托管堆的语言,因为无需担心依赖关系的生命周期结束。但是其他类型的语言呢?
例如,在传统的malloc
和free
环境中,分配内存的方法通常也应该释放它。我不确定如何通过DI实现这一目标。
或者使用需要引用计数的存储器方案,例如COM,我不确定调用者何时会在依赖项上调用Release
,或者接收注入的对象应该调用Release
两次。
是否可以在没有托管堆的情况下使用DI?如果是这样,哪些代码模式可以很好地确保资源正确释放?
答案 0 :(得分:1)
对我来说DI和垃圾收集是无关的。您只需要组织内存管理。从尝试到处使用静态对象开始。如果您的DI图是静态的(即在应用程序工作期间它没有改变),这将起作用。
如果您的DI图表正在发展或在应用程序启动期间确定其结构,则需要有关如何执行此操作的更多信息。我不确定适合每种情况的一般解决方案是否可行。修改DI图的实体应负责清理。完全与在其他情况下在C ++中完成的方式相同。例如,您可以将DI代理对象放入一个静态容器中,该容器将在应用程序工作结束时被销毁(如果所有内容都已正确组织其内容)。
在C / C ++中,需要以这种或那种方式管理内存管理容器,连接和其他许多东西。我不明白为什么DI很特别。垃圾收集解决了它所用的所有内容的内存管理(仍有其自身的缺点)。
答案 1 :(得分:1)
但是其他类型的语言呢?是否可以在没有托管堆的情况下使用DI?
拥有托管堆不是DI的先决条件。例如,C ++不是托管语言,但是它有DI框架,可与用于托管语言(如Java)的DI框架的功能相媲美C#。
Daniele Pallastrelli的精彩演讲Going native with less coupling - Dependency Injection in C++详细解释了DI对其他两种解耦技术(工厂和服务定位器)的好处。它还提供了一个名为Wallaroo的C ++ DI框架,并解释了它的内部结构。
另一个C ++ DI框架,基于不同的方法,然后Wallaroo是[Boost].DI。我强烈建议您阅读“简介”一章。它为“我是否已经使用依赖注入?”,“我是否需要依赖注入?”等问题提供了简短但很好的答案。
我想提到的第三个C ++ DI框架是Infector++。
这些只是众多C ++ DI框架中的三个。您可以在this page上找到大量列出的内容。
我的观点是,如果有很多用于C ++的DI框架,无论它们是否被广泛接受,肯定有可能没有托管堆的DI: - )
如果是这样,哪些代码模式可以很好地确保资源正确释放?
上面的链接提供了关于如何在C ++中完成DI框架的额外输入,包括依赖项解析,不同的创建策略和对象范围,最后是您的问题,即对象生命周期管理。
在这里,我将简要概述生命周期管理如何一致且确定性地完成。所有提到的框架都大量使用智能指针(std::unique_ptr
,std::shared_ptr
,如果它们提供Boost支持,也使用boost::shared_ptr
并将创建策略语义附加到它们。请注意,您不需要完整的DI框架来使用此模式。基本思路很简单。
假设我声明了一个类似下面的类:
class i_depend_on_others {
i_depend_on_others(std::unique_ptr<other>,
std::shared_ptr<another_other>,
boost::shared_ptr<yet_another_other>)
{ }
};
这是一个明确的构造函数注入,但附加了关于“其他”的预期生命周期的语义。第一个other
将由i_depend_on_others
实例拥有,由于我们拥有std::unique_ptr
,因此只要删除i_depend_on_others
实例,它就会被删除。 another_other
和yet_another_other
的生命周期应与i_depend_on_others
实例无关。这种模式清楚地定义了何时i_depend_on_others
实例负责清理资源以及何时调用代码应该这样做。 (在DI框架的情况下,框架负责共享实例。)
问题是在这种情况下该怎么做:
class i_depend_on_others_as_well {
i_depend_on_others_as_well(other*) { }
};
(我将在此处讨论在现代C ++开发中应避免使用原始指针。假设我们被迫使用它们。)
同样,该模式定义了明确的语义。 原始指针意味着所有权转移。 i_depend_on_others_as_well
的实例负责删除other
。
对于像[Boost].DI这样的DI框架,指针的类型将决定注入对象的默认生命周期。对于共享指针,它们将是singeltons,创建一次并由[Boost] .DI维护,对于原始指针和唯一指针,每次都会创建一个新实例。
可以在[Boost] .DI文档的"Decide the life times"章节中找到有关此模式的更详细说明。