我使用C#和Autofac 4.9.4。我有一个连接到IComponentRegistration.Activated事件的Autofac模块。它查找某些类的激活实例,并将它们注册到某个管理器类中。当然,这种注册应仅限于受影响对象的寿命。因此,模块需要知道何时容器将对象丢弃,然后从管理器中注销它。否则会产生内存泄漏。当我在autofac ContainerBuilder中注册一个类时,有一个OnRelease-Method,但这不是正确的位置。我在模块中需要这样的事件。
具体代码看起来像这样:
using Autofac;
using Autofac.Core;
namespace De.Gedat.Foundation.Bl.IoC
{
public class ResetManagerModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
registration.Activated += (sender, e) =>
RegisterToResetManager(e.Instance, e.Context);
registration.Released += ???
}
private void RegisterToResetManager(object instance, IComponentContext context)
{
// Every IAutoRegisteredResettable object created by IoC will be picked up:
var resettable = instance as IAutoRegisteredResettable;
if (resettable == null)
return;
// Get the singleton IResetManager...
var resetManager = context.Resolve<IResetManager>();
// ...and register the instance with it:
resetManager.RegisterInstance(resettable);
// ...and on resettable's end-of-lifetime we would have to call:
//resetManager.UnregisterInstance(resettable)
//...but not at this point when the instance has just been created!
}
}
}
如何丢弃对象时会引起注意?
[假设存在生命周期的范围,我们本来希望让autofac为我们处理所有处置,所以最好使用using语句包装上下文,但是它也将处置resettable
,因此我们将无法处置致电resetManager.UnregisterInstance(resettable)
。
[为了不处置您的resettable
实例,并在处置生存期范围时仍让autofac处理所有处置,我们可以使用ExternallyOwned
(doc告诉我们要自己处理它: ,然后在finally
语句中调用resetManager.UnregisterInstance(resettable)
,然后手动处理实例。
private void RegisterToResetManager(object instance, IComponentContext context)
{
var resettable = instance as IAutoRegisteredResettable;
if (resettable == null)
return;
var resetManager = context.Resolve<IResetManager>();
try
{
resetManager.RegisterInstance(resettable).ExternallyOwned();
}
finally
{
resetManager.UnregisterInstance(resettable);
resettable.Dispose();
}
}