Autofac:需要:在 AutofacModule 中处理的实例的生命周期结束事件
Autofac: Needed: End-Of-Lifetime event for instances handled in a AutofacModule
我使用 C# 和 Autofac 4.9.4。
我有一个连接到 IComponentRegistration.Activated 事件的 Autofac 模块。它查找某些 classes 的激活实例,并将它们注册到某个管理器 class 中。
当然,此注册应限于受影响对象的生命周期。所以模块需要知道对象何时被容器丢弃,然后从管理器中注销它。否则我会产生内存泄漏。
当我向 autofac ContainerBuilder 注册 class 时,有一个 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 处理所有处理,我们可以告诉 autofac 我们想用 [=14 自己处理它=] (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();
}
}
我们想出了以下完美的解决方案:
public class ResetManagerAutofacModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistryBuilder componentRegistryBuilder,
IComponentRegistration registration)
{
registration.Activated += (sender, e) =>
RegisterToResetManager(e.Instance, e.Context);
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ResetManager>().As<IResetManager>().SingleInstance();
// Because there are no module events for the end-of-lifetime of objects,
// we use a disposable class as a helper to get informed about disposal
// (declaration see below):
builder
.RegisterType<DisposeObserver>()
.InstancePerDependency(); // important!!!
}
private void RegisterToResetManager(object instance, IComponentContext context)
{
var resettable = instance as IAutoRegisteredResettable;
if (resettable == null)
return;
var resetManager = context.Resolve<IResetManager>();
// Hook the object on the manager:
resetManager.RegisterInstance(resettable);
// Get a new instance of our dispose helper class from the container
// which has the same lifetime as "instance" because DisposeObserver
// is registered as InstancePerDependency.
var disposableWithCallback = context.Resolve<DisposeObserver>();
// When this helper is disposed, we know that the lifetime of "instance" is over.
disposableWithCallback.DisposingCallback =
// So we can unhook it from the manager:
() => resetManager.UnregisterInstance(resettable);
}
public class DisposeObserver : IDisposable
{
public Action DisposingCallback { get; set; }
public void Dispose()
{
DisposingCallback?.Invoke();
DisposingCallback = null;
}
}
}
我使用 C# 和 Autofac 4.9.4。 我有一个连接到 IComponentRegistration.Activated 事件的 Autofac 模块。它查找某些 classes 的激活实例,并将它们注册到某个管理器 class 中。 当然,此注册应限于受影响对象的生命周期。所以模块需要知道对象何时被容器丢弃,然后从管理器中注销它。否则我会产生内存泄漏。 当我向 autofac ContainerBuilder 注册 class 时,有一个 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 处理所有处理,我们可以告诉 autofac 我们想用 [=14 自己处理它=] (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();
}
}
我们想出了以下完美的解决方案:
public class ResetManagerAutofacModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistryBuilder componentRegistryBuilder,
IComponentRegistration registration)
{
registration.Activated += (sender, e) =>
RegisterToResetManager(e.Instance, e.Context);
}
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ResetManager>().As<IResetManager>().SingleInstance();
// Because there are no module events for the end-of-lifetime of objects,
// we use a disposable class as a helper to get informed about disposal
// (declaration see below):
builder
.RegisterType<DisposeObserver>()
.InstancePerDependency(); // important!!!
}
private void RegisterToResetManager(object instance, IComponentContext context)
{
var resettable = instance as IAutoRegisteredResettable;
if (resettable == null)
return;
var resetManager = context.Resolve<IResetManager>();
// Hook the object on the manager:
resetManager.RegisterInstance(resettable);
// Get a new instance of our dispose helper class from the container
// which has the same lifetime as "instance" because DisposeObserver
// is registered as InstancePerDependency.
var disposableWithCallback = context.Resolve<DisposeObserver>();
// When this helper is disposed, we know that the lifetime of "instance" is over.
disposableWithCallback.DisposingCallback =
// So we can unhook it from the manager:
() => resetManager.UnregisterInstance(resettable);
}
public class DisposeObserver : IDisposable
{
public Action DisposingCallback { get; set; }
public void Dispose()
{
DisposingCallback?.Invoke();
DisposingCallback = null;
}
}
}