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

如何为有状态对象树实现依赖注入?

解决方案

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:40:22