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

如何在C#依赖注入中正确创建带构造参数的对象?

如何通过依赖注入创建带运行时参数的对象

针对你需要为每个从INI读取的Id创建SomeClass实例的场景,下面提供几种规范的原生DI实现方式,避免直接new的同时,保留DI自动注入其他依赖的能力:

方案一:基于抽象工厂+ActivatorUtilities(推荐)

这种方式既保留工厂模式的灵活性,又能让DI容器负责解析SomeClass的其他依赖(比如后续添加的ILogger、其他服务等),无需修改工厂代码。

步骤1:定义工厂接口

public interface ISomeClassFactory
{
    SomeClass Create(int id);
}

步骤2:实现工厂(依赖IServiceProvider)

利用原生DI的ActivatorUtilities工具类,让容器自动解析SomeClass的所有依赖,仅传入运行时确定的Id参数:

public class SomeClassFactory : ISomeClassFactory
{
    private readonly IServiceProvider _serviceProvider;

    public SomeClassFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public SomeClass Create(int id)
    {
        // 容器会自动注入SomeClass构造函数中除了id之外的其他依赖
        return ActivatorUtilities.CreateInstance<SomeClass>(_serviceProvider, id);
    }
}

步骤3:注册工厂和服务

var builder = Host.CreateApplicationBuilder(e.Args);
// 注册SomeClass
builder.Services.AddTransient<SomeClass>();
// 注册工厂
builder.Services.AddTransient<ISomeClassFactory, SomeClassFactory>();

步骤4:使用工厂创建实例

在需要创建实例的地方,通过构造函数注入工厂,然后批量创建:

// 假设在某个服务中注入工厂
public class YourBusinessService
{
    private readonly ISomeClassFactory _someClassFactory;

    public YourBusinessService(ISomeClassFactory someClassFactory)
    {
        _someClassFactory = someClassFactory;
    }

    public void ProcessIds()
    {
        List<int> ids = readIdsFromIni();
        foreach(var id in ids)
        {
            SomeClass instance = _someClassFactory.Create(id);
            // 处理实例逻辑
        }
    }
}

方案二:直接使用ActivatorUtilities(简化版)

如果不需要抽象工厂的解耦(比如场景简单,不需要替换工厂实现),可以直接在需要创建实例的地方注入IServiceProvider,然后调用ActivatorUtilities:

public class YourBusinessService
{
    private readonly IServiceProvider _serviceProvider;

    public YourBusinessService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public void ProcessIds()
    {
        List<int> ids = readIdsFromIni();
        foreach(var id in ids)
        {
            SomeClass instance = ActivatorUtilities.CreateInstance<SomeClass>(_serviceProvider, id);
            // 处理实例逻辑
        }
    }
}

为什么这比直接new好?

如果后续SomeClass的构造函数添加了新的依赖(比如日志服务):

public class SomeClass
{
    public SomeClass(int id, ILogger<SomeClass> logger)
    {
        Id = id;
        _logger = logger;
    }
    public int Id {get;}
    private readonly ILogger<SomeClass> _logger;
}

使用上述方案时,DI容器会自动注入ILogger<SomeClass>,无需修改创建实例的代码;而直接new的话,需要手动传入所有新添加的依赖,维护成本更高。

内容的提问来源于stack exchange,提问作者Petr Daricek

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 17:42:35