如何在Autofac中实现子生命周期作用域的自动销毁?
Autofac 子生命周期作用域自动销毁解决方案
线性单链父子作用域场景
你当前的实现逻辑符合Autofac的API设计规范,可封装为扩展方法减少样板代码,降低出错概率:
public static class LifetimeScopeExtensions { /// <summary> /// 创建子作用域,子作用域销毁时自动销毁父作用域 /// </summary> public static ILifetimeScope BeginLifetimeScopeWithParentDisposal(this ILifetimeScope parent, Action<ContainerBuilder> configuration = null) { var childScope = configuration == null ? parent.BeginLifetimeScope() : parent.BeginLifetimeScope(configuration); childScope.Disposer.AddInstanceForDisposal(parent); return childScope; } }
使用时直接调用扩展方法即可,和原生API使用逻辑完全对齐:
ILifetimeScope scope = ...; scope = scope.BeginLifetimeScopeWithParentDisposal(b => { // 补充/替换子作用域注册项 });
多子作用域共享父作用域场景
你设想的引用计数方案是这类共享资源销毁的标准实现思路,完全可以落地,以下是可直接复用的线程安全实现:
第一步:实现引用计数管理器
public class ScopeReferenceManager : IDisposable { private readonly ILifetimeScope _parentScope; private int _referenceCount; private readonly object _lockObj = new(); public ScopeReferenceManager(ILifetimeScope parentScope) { _parentScope = parentScope; } public void Increment() { lock (_lockObj) { _referenceCount++; } } public void Decrement() { lock (_lockObj) { _referenceCount--; if (_referenceCount == 0) { _parentScope.Dispose(); } } } public void Dispose() { Decrement(); } }
第二步:封装扩展方法
public static class LifetimeScopeExtensions { /// <summary> /// 创建带引用计数的子作用域,所有子作用域销毁后父作用域自动销毁 /// </summary> public static ILifetimeScope BeginReferencedLifetimeScope(this ILifetimeScope parent, Action<ContainerBuilder> configuration = null) { // 首次创建子作用域时注册引用管理器 if (!parent.TryResolve(out ScopeReferenceManager referenceManager)) { var builder = new ContainerBuilder(); builder.RegisterInstance(new ScopeReferenceManager(parent)) .SingleInstance() .ExternallyOwned(); builder.Update(parent.ComponentRegistry); referenceManager = parent.Resolve<ScopeReferenceManager>(); } referenceManager.Increment(); var childScope = configuration == null ? parent.BeginLifetimeScope() : parent.BeginLifetimeScope(configuration); // 子作用域销毁时自动扣减计数 childScope.Disposer.AddInstanceForDisposal(referenceManager); return childScope; } }
注意:不要将引用计数方案用于Autofac根容器,根容器的生命周期应该和应用进程生命周期绑定,在应用退出时手动销毁即可。
等效UnityDisposer的整树销毁实现
Autofac的ILifetimeScope暴露了Children属性可获取所有直接子作用域,可通过递归实现整树销毁,功能和你之前用的UnityDisposer完全一致:
public static class LifetimeScopeExtensions { /// <summary> /// 递归销毁当前作用域及所有子作用域 /// </summary> public static void DisposeScopeTree(this ILifetimeScope rootScope) { foreach (var child in rootScope.Children) { child.DisposeScopeTree(); } rootScope.Dispose(); } }
内容的提问来源于stack exchange,提问作者void.pointer
相关产品推荐
相关产品推荐

