You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core DI手动创建实例释放方法与工厂注册生命周期差异

问题1:实现框架自动释放手动创建的IDBCache实例的可行方案

.NET Core依赖注入容器只会自动释放自身托管创建的服务实例,手动new的实例要实现自动释放,可选择适配不同场景的方案:

  • 方案1:.NET 8+ 使用键控服务(最简洁)
    直接将IDBCache注册为以userId为Key的托管服务,容器自动处理生命周期:
    // 注册键控服务,根据userId区分实例
    container.AddKeyedTransient<IDBCache>((sp, key) => 
        new IDBCache((string)key, sp.GetRequiredService<IBLogic>()));
    // 注册工厂方便调用
    container.AddSingleton<Func<string, IDBCache>>(sp => 
        userId => sp.GetRequiredKeyedService<IDBCache>(userId));
    
    容器会按照注册的生命周期(示例为瞬态,可根据需求改成Scoped/Singleton)自动释放实现了IDisposable/IAsyncDisposable的IDBCache实例。
  • 方案2:低版本.NET 挂载到当前作用域释放
    如果是ASP.NET Core场景,可将创建的实例注册到当前请求的释放队列:
    container.AddSingleton<Func<string, IHttpContextAccessor, IDBCache>>(p => 
        (userId, accessor) => 
        {
            var cache = new IDBCache(userId, p.GetRequiredService<IBLogic>());
            // 挂载到当前请求,请求结束自动释放
            accessor.HttpContext?.Response.RegisterForDispose(cache);
            return cache;
        });
    
    非Web场景可在创建实例后,手动挂载到当前IServiceScope的释放列表,作用域销毁时自动释放。

问题2:用AddSingleton注册工厂委托的优势

你注册的Func<string, IDBCache>本身是一个无状态的委托对象,逻辑固定,不依赖任何作用域内的服务:

  • AddSingleton注册时,整个应用生命周期只会创建1次该委托实例,所有位置解析到的都是同一个委托,没有重复初始化的开销,性能最优,也不存在线程安全问题。
  • 如果用AddTransient注册,每次解析工厂都会生成新的委托实例,完全无意义,只会产生不必要的内存分配和GC开销。
  • 如果用AddScoped注册,每个作用域都会生成一个新的委托实例,同样属于冗余操作,没有收益。

注意:如果后续工厂内部需要解析作用域服务,不能再用AddSingleton注册工厂,否则会捕获根容器导致作用域服务泄漏,此时需改为AddScoped注册工厂,捕获当前作用域的服务提供者。


内容的提问来源于stack exchange,提问作者191180rk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 03:15:07