C# DI容器注入含非已注册构造参数类的配置方法
正确注册实现方式
你使用显式工厂委托注册时,委托入参sp是当前DI容器的服务提供实例,可直接从该实例解析出已注册的IHttpClientFactory,再手动传入你自定义的s1、s2实际值即可,完整写法如下:
// 替换为你业务中s1、s2需要的实际值,也可从配置文件读取 string customS1 = "第一个字符串参数的实际业务值"; string customS2 = "第二个字符串参数的实际业务值"; services.AddScoped<IInterface>(sp => { // 从容器中解析已注册的IHttpClientFactory依赖 var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); // 传入全部构造参数完成实例化 return new Concrete(httpClientFactory, customS1, customS2); });
注意事项
- 推荐使用
GetRequiredService<T>()解析容器内已注册的依赖:如果依赖因配置缺失无法解析,该方法会立刻抛出明确的异常,比GetService<T>()返回null后触发空引用问题更易排错。 - 你之前参考的写法
services.AddScoped<IInterface, Concrete>(sp => {})中第二个泛型参数Concrete属于冗余写法,因为你已经在工厂委托中手动创建了Concrete实例,省略该泛型参数即可,保留也不会引发运行错误。 - 如果你的
s1、s2值来自配置文件,可在注册阶段直接从IConfiguration实例读取对应配置项后传入,无需将字符串本身注册到DI容器。
可选优化方案
如果你定义的Concrete类全程只使用你之前注册的名为clientName的HttpClient,不需要动态创建其他命名客户端,可以直接调整构造函数依赖为HttpClient,注册时直接解析对应命名客户端传入,省掉类内部手动调用CreateClient的步骤:
// 调整后类构造示例 public class Concrete : IInterface { private readonly HttpClient _client; private readonly string _s1; private readonly string _s2; public Concrete(HttpClient client, string s1, string s2) { _client = client; _s1 = s1; _s2 = s2; } } // 对应注册写法 services.AddScoped<IInterface>(sp => { var httpClientFactory = sp.GetRequiredService<IHttpClientFactory>(); var namedClient = httpClientFactory.CreateClient("clientName"); return new Concrete(namedClient, customS1, customS2); });
内容的提问来源于stack exchange,提问作者Omar93
相关产品推荐
相关产品推荐

