如何为有状态对象树实现依赖注入?
解决方案
1. 用DI容器的工厂委托(ASP.NET Core场景)
ASP.NET Core的DI支持注册Func<T>委托作为工厂,自动帮你解析容器管理的依赖,只需传入动态参数:
首先在Startup/Program.cs里注册:
services.AddTransient<SocketHandler>(); services.AddSingleton<Func<int, SocketHandler>>(sp => socketId => new SocketHandler(socketId, sp.GetRequiredService<ILogger<DataProcessingService>>()) );
然后在控制器中注入这个工厂,创建实例:
private readonly Func<int, SocketHandler> _socketHandlerFactory; private readonly Dictionary<int, SocketHandler> _activeHandlers = new(); public SocketController(Func<int, SocketHandler> socketHandlerFactory) { _socketHandlerFactory = socketHandlerFactory; } [HttpPost("sockets/{id}/subscribe")] public IActionResult Subscribe(int id) { if (!_activeHandlers.ContainsKey(id)) { var handler = _socketHandlerFactory(id); _activeHandlers.Add(id, handler); } return Ok(); } [HttpPost("sockets/{id}/unsubscribe")] public IActionResult Unsubscribe(int id) { if (_activeHandlers.TryGetValue(id, out var handler)) { handler.Dispose(); _activeHandlers.Remove(id); } return Ok(); }
2. 自定义工厂类(解耦创建逻辑)
如果创建逻辑复杂,或者想和控制器解耦,可以写一个专门的工厂类:
public interface ISocketHandlerFactory { SocketHandler Create(int socketId); } public class SocketHandlerFactory : ISocketHandlerFactory { private readonly IServiceProvider _serviceProvider; public SocketHandlerFactory(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public SocketHandler Create(int socketId) { var logger = _serviceProvider.GetRequiredService<ILogger<DataProcessingService>>(); return new SocketHandler(socketId, logger); } }
注册工厂:
services.AddSingleton<ISocketHandlerFactory, SocketHandlerFactory>();
控制器里使用:
private readonly ISocketHandlerFactory _factory; private readonly Dictionary<int, SocketHandler> _activeHandlers = new(); public SocketController(ISocketHandlerFactory factory) { _factory = factory; } [HttpPost("sockets/{id}/subscribe")] public IActionResult Subscribe(int id) { if (!_activeHandlers.ContainsKey(id)) { var handler = _factory.Create(id); _activeHandlers.Add(id, handler); } return Ok(); }
3. 用ActivatorUtilities自动解析依赖
如果SocketHandler后续要加很多依赖,手动写工厂会很繁琐,用ActivatorUtilities可以让容器自动解析所有已注册的依赖,只需传入动态参数:
修改工厂类的Create方法:
public SocketHandler Create(int socketId) { return ActivatorUtilities.CreateInstance<SocketHandler>(_serviceProvider, socketId); }
这样不管SocketHandler的构造函数加多少DI管理的依赖,都不用修改工厂代码,容器会自动帮你注入。
核心思路
本质是把**动态参数(socketId)和容器托管的无状态依赖(ILogger等)**拆分处理:
- 无状态服务交给DI容器管理,复用实例
- 动态参数在实例化时手动传入
- 通过工厂类/委托整合两者,避免手动创建所有依赖,保持DI的优势
内容的提问来源于stack exchange,提问作者yaskovdev
相关产品推荐
相关产品推荐

