.NET Core自定义服务工厂自动释放问题:实例Dispose未触发求助
问题确认与解决方案
推测正确性确认
你的推测完全正确。.NET的DI容器(ServiceProvider)仅会跟踪由它自身创建的实现IDisposable接口的服务实例。当自定义工厂绕过ServiceProvider直接实例化服务(比如用new MyService(...))时,容器无法感知这些实例的存在,因此在ASP.NET服务器关闭、容器释放时,不会调用这些实例的Dispose方法。
触发Dispose的可行方案
方案1:让工厂通过ServiceProvider创建实例
不要直接new服务,而是通过IServiceProvider或IServiceScopeFactory来创建实例,让容器跟踪这些实例:
public class MyServiceFactory { private readonly IServiceScopeFactory _scopeFactory; public MyServiceFactory(IServiceScopeFactory scopeFactory) { _scopeFactory = scopeFactory; } public MyService CreateService(MyConfig config) { // 创建独立作用域,用于管理该实例的生命周期 var scope = _scopeFactory.CreateScope(); var provider = scope.ServiceProvider; // 从DI获取依赖,结合自定义配置创建实例 var dependency = provider.GetRequiredService<IMyDependency>(); var service = ActivatorUtilities.CreateInstance<MyService>(provider, dependency, config); // 若需长期持有实例,需保留scope引用,在合适时机手动释放scope以触发Dispose return service; } }
注意:如果需要长期持有创建的服务实例,不能用using包裹scope,否则scope释放时实例会被立即销毁。此时需保留scope引用,在服务器关闭或实例不再被使用时手动释放scope,触发实例的Dispose。
方案2:工厂自行跟踪实例并在应用关闭时释放
如果必须绕过ServiceProvider创建实例,可让工厂自行维护实例列表,并在应用关闭时手动调用Dispose:
public class MyServiceFactory : IDisposable { private readonly ConcurrentBag<MyService> _createdServices = new(); private readonly IHostApplicationLifetime _appLifetime; public MyServiceFactory(IHostApplicationLifetime appLifetime) { _appLifetime = appLifetime; // 注册应用关闭事件,触发实例销毁 _appLifetime.ApplicationStopping.Register(DisposeAllServices); } public MyService CreateService(MyConfig config) { var service = new MyService(config); _createdServices.Add(service); return service; } private void DisposeAllServices() { foreach (var service in _createdServices) { service.Dispose(); } } public void Dispose() { DisposeAllServices(); } }
这种方式需注意线程安全,避免实例创建与销毁时的并发冲突。
方案3:用ActivatorUtilities让容器参与实例创建
如果服务部分依赖来自DI、部分是自定义配置,可使用ActivatorUtilities.CreateInstance方法——它会从ServiceProvider解析构造函数依赖,同时允许传入自定义参数,创建的实例会被容器跟踪(需在指定scope内创建):
public MyService CreateService(IServiceProvider provider, MyConfig config) { var service = ActivatorUtilities.CreateInstance<MyService>(provider, config); // 若需容器完全管理生命周期,可将实例注册到当前scope的服务集合中 // provider.GetRequiredService<IServiceCollection>().AddSingleton(service); return service; }
内容的提问来源于stack exchange,提问作者monty
相关产品推荐
相关产品推荐

