【发布时间】:2015-10-15 19:01:31
【问题描述】:
我注意到,当我通过简单的注入器添加装饰器时,容器不会超出范围。有谁知道这是否是预期的?如果我不添加装饰器,则容器将被垃圾收集。否则,它不是。我应该做些什么来强制清理?
这是一个简单的例子。如果添加了装饰器,则在“运行”完成后容器仍在内存中。如果没有添加装饰器,容器会被 GC'ed。
public interface IDoSomething { }
public class DoSomething: IDoSomething { }
public class DoSomethingDec1: IDoSomething {
public DoSomethingDec1(IDoSomething handler) { }
}
public class DoSomethingDec2 : IDoSomething {
public DoSomethingDec2(IDoSomething handler) { }
}
static void Main(string[] args) {
Console.WriteLine("Press a key to start");
Console.ReadKey(true);
Run();
GC.Collect();
Console.WriteLine("Done");
Console.ReadKey(true);
}
static void Run() {
//can be re-created with 1 container; easier to see with multiple
for (var i = 0; i < 1000; i++) {
using (var container = new Container()) {
container.Register<IDoSomething, DoSomething>();
//Comment out these 2 lines to remove the decorators
container.RegisterDecorator<IDoSomething, DoSomethingDec1>();
container.RegisterDecorator<IDoSomething, DoSomethingDec2>();
container.Verify();
container.GetInstance<IDoSomething>();
}
}
}
使用装饰器:
没有装饰器:
【问题讨论】:
-
为什么要创建多个容器实例?文档advices 创建单个容器实例并警告不 创建“无限数量的容器实例”。
-
嗨史蒂文,该示例创建多个以使其更容易发现。但是,这仅发生在一个容器中。我正在创建一个在内部使用简单注入器(单个容器)的库 - 我无法确定用户何时会处置我的根对象(其中包含 SI 容器)。这就是我注意到容器没有释放的原因。
-
看来我们遇到了内存泄漏。我能够重现这一点。我还不清楚为什么这些实例会保持活动状态,但请放心,这不是故意的,是一个错误,我们会找到原因并修复此问题。
-
但也就是说,在库中使用 DI 容器可能不是最佳选择。阅读 Mark Seemann 的 this excellent post 了解 DI 友好库。
-
谢谢史蒂文。我会看看你链接的帖子。如果有什么不同的话,我对简单注入器的使用是一个实现细节。库本身没有直接指示正在使用 SI - 用户从不直接与其交互。
标签: c# memory-leaks dependency-injection simple-injector