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

.NET中如何向IOC容器已创建的字典类型服务追加内容?

解决.NET中IOC容器内字典追加条目的问题

问题原因

你之前用GetService<Dictionary<string, List<SomeInterface>>>()追加条目无效,核心原因是原注册用的AddScoped——每次调用GetService都会触发工厂方法创建全新的字典实例,你修改的只是临时实例,后续获取的还是新创建的原字典,所以看不到追加效果。

解决方案

既然原注册代码无法修改,我们可以通过覆盖Scoped注册的方式,在原有字典基础上追加内容:

// 原有的注册代码(无法修改)
builder.Services.AddScoped(sp =>
{
    var options = sp.GetService<IOptionsMonitor<CommonOption>>().CurrentValue;
    var demoOptions = new Dictionary<string, List<SomeInterface>>();

    foreach (var kvp in options)
    {
        if(kvp.Key != "X")
        {
            continue;
        }
        var demoList = kvp.Value.Select(item => SomeMethod(item)).ToList();
        demoOptions.Add(kvp.Key, demoList);
    }
    return demoOptions;
});

// 追加Key不等于"X"的条目,覆盖原Scoped注册
builder.Services.AddScoped<Dictionary<string, List<SomeInterface>>>(sp =>
{
    // 获取原工厂创建的字典实例
    var baseDictionary = sp.GetRequiredService<Dictionary<string, List<SomeInterface>>>();
    var options = sp.GetRequiredService<IOptionsMonitor<CommonOption>>().CurrentValue;

    foreach (var kvp in options)
    {
        // 跳过已包含的"X"条目,追加其他Key
        if (kvp.Key == "X") continue;

        var itemList = kvp.Value.Select(item => SomeMethod(item)).ToList();
        // 避免重复添加,若Key已存在可选择覆盖或跳过
        if (!baseDictionary.ContainsKey(kvp.Key))
        {
            baseDictionary.Add(kvp.Key, itemList);
        }
        // 如需更新已有Key的内容,替换为:baseDictionary[kvp.Key] = itemList;
    }

    return baseDictionary;
});

原理说明

  1. 当第一次请求获取Dictionary<string, List<SomeInterface>>时,会先执行原工厂创建只含"X"条目的字典。
  2. 紧接着执行我们新增的工厂方法,拿到这个字典实例并追加其他条目,最终返回修改后的实例。
  3. 同一请求内后续获取该字典时,IOC容器会返回已经修改好的实例,不会再重复创建。

注意事项

  • 因为是Scoped生命周期,每个请求的字典实例独立,无需担心多线程并发修改问题。
  • 如果需要确保条目不会被重复添加,一定要判断ContainsKey,避免抛出异常。

内容的提问来源于stack exchange,提问作者Bushra Saifi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 07:15:14