城堡温莎类型工厂没有释放不泄漏

本文关键字:释放 泄漏 工厂 类型 城堡 | 更新日期: 2023-09-27 18:15:21

我使用城堡温莎类型的工厂。在我们的注册代码中,它可以创建一个Transient组件:

container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IThingFactory>().AsFactory());
container.Register(Component.For<IThing>().ImplementedBy<TransientObject>().Named("TransientObject").LifeStyle.Transient);

根据我对Castle Windsor类型化工厂文档的理解,我认为瞬态对象必须由类型化工厂方法释放,否则类型化工厂将保留对该对象的引用。我试图通过编写一个测试来证明这一点,该测试使用了这篇StackOverflow文章中解释的方法。

但令我惊讶的是,它实际上并没有失败,这意味着尽管我没有将瞬态对象释放回工厂,但它仍然可以被GC回收。我担心我的测试可能会误导人,真的有泄漏。

所以我的问题是:是我的测试错了,还是文档错了?

下面是测试:

var factory = container.Resolve<IThingFactory>();
WeakReference reference = null;
new Action(() =>
        {
            var service = factory.GetTransientObject();
            reference = new WeakReference(service, true);
        })();
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.That(reference.Target, Is.Null, "reference should be null");

城堡温莎类型工厂没有释放不泄漏

Windsor仅在Transient实例存在退役问题时才跟踪它们。一个典型的退役问题的例子是一个类实现了IDisposable接口。

所以,如果IThingTransient,它没有实现IDisposable ,它没有任何其他退役问题,那么温莎将不会跟踪它,垃圾收集器可以/将删除IThing的实例。

但是(这是一个很大的但是),我建议您不要依赖此行为。IThing可能会被开发人员更改,将来可能会变成一次性的。或者它可能会引起另一个退役问题。突然就发生了内存泄漏。因此,应该遵循一个简单的规则:

任何时候通过调用container.Resolve显式解析对象时,它必须通过调用container.Release来释放。同样,任何时候一个对象被类型工厂显式地创建,它必须被类型工厂显式地销毁。对象是否是暂态并不重要,要注意它的生命周期。总是这样。对象的创建者(无论是windsor还是typed factory)负责销毁该对象。

基本上,@piotrwest的评论是对的。然而,这个答案的目的是解释它不仅仅是关于IDisposable -它是关于退役问题(IDisposable只是其中之一)。