.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; });
原理说明
- 当第一次请求获取
Dictionary<string, List<SomeInterface>>时,会先执行原工厂创建只含"X"条目的字典。 - 紧接着执行我们新增的工厂方法,拿到这个字典实例并追加其他条目,最终返回修改后的实例。
- 同一请求内后续获取该字典时,IOC容器会返回已经修改好的实例,不会再重复创建。
注意事项
- 因为是Scoped生命周期,每个请求的字典实例独立,无需担心多线程并发修改问题。
- 如果需要确保条目不会被重复添加,一定要判断
ContainsKey,避免抛出异常。
内容的提问来源于stack exchange,提问作者Bushra Saifi
相关产品推荐
相关产品推荐

