简单的注入器 - 导致容器不被垃圾收集的装饰器?

Simple injector - decorators causing container to not be garbage collected?

我注意到当我通过简单注入器添加装饰器时,容器不会超出范围。有谁知道这是否是预期的?如果我不添加装饰器,容器就会被垃圾回收。否则,它不是。有什么我应该做的来强制清理吗?

这是一个简单的例子。如果添加装饰器,容器在 'Run' 完成后仍在内存中。如果不添加装饰器,容器将被 GC 处理。

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>();
        }
    }
}

有装饰器:

没有装饰器:

更新:此问题已在 v3.1.1.

中修复

问题是由 引起的,如果图包含 ThreadLocal<T>,它会使循环对象图保持活动状态。在 Simple Injector 的情况下,装饰器子系统将 ThreadLocal<T> 添加到 ContainerItems 字典中。 ThreadLocal 的值再次间接引用 Container,导致图形变为循环。由于 .NET 中的错误,ThreadLocal<T> 被认为是活动的,保持其依赖对象,例如 Container 活动。 Container 实例再次使其他一切保持活动状态,这显然会导致内存泄漏。

尽管我们可以等待 Microsoft 修复此问题,但这可能需要很长时间。所以我们的计划是在未来的补丁版本中解决这个问题。我们可能会将 .NET 的 ThreadLocal<T> 替换为我们自己的不会导致内存泄漏的自定义实现。此自定义实现已在 Simple Injector 的 PCL 库中使用,因为 ThreadLocal<T> 不适用于 PCL。这意味着 PCL 版本的 Simple Injector 没有这个问题。