.NET6注入多实现服务报错:部分服务无法构造的原因排查
问题:.NET6中注入泛型服务时出现构造失败错误
我正在.NET6中注入实现了IDBActionQuery<T>接口的多个服务,已经在Program.cs中添加了以下代码:
builder.Services.AddTransient<IDBActionQuery<Period>, Select<Period>>();
定义的IDBActionQuery<T>接口如下:
public interface IDBActionQuery<T> { Task<List<T>> execute(string query, params (string name, object val)[] pars); Task<List<T>> buildAndExecute(); }
对应的Select<T>实现类:
public class Select<T> : DBMotorBase<T>, IDBActionQuery<T> { private readonly IPrintExceptions exceptions; private readonly IGetPropertiesService propertiesService; private readonly ISQLParametersService sqlParameterService; private readonly ISerializeService serializeService; private readonly IDeserealizeService<T> deserealizeService; public Select(string _connection, IPrintExceptions _exceptions, IGetPropertiesService _propertiesService, ISQLParametersService _sqlParameterService, ISerializeService _serializeService, IDeserealizeService<T> _deserealizeService) : base(_connection) { exceptions = _exceptions; propertiesService = _propertiesService; sqlParameterService = _sqlParameterService; serializeService = _serializeService; deserealizeService = _deserealizeService; } private string build(string schema = "dbo") { ... } public async Task<List<T>> buildAndExecute() { return await execute(build(),null); } public async Task<List<T>> execute(string query, params (string name, object val)[] pars) { ... } private async Task<List<T>> processCommand(SqlConnection sql, string query, params (string name, object val)[] pars) { ... } private async Task<List<T>> processReader(SqlCommand cmd) { .... } }
运行时出现错误:Some services are not able to be constructed (Error while validating the service descriptor 'ServiceType:,请问错误原因是什么?
错误原因分析
- 无法解析构造函数中的
string _connection参数:依赖注入容器默认只能解析已注册的服务类型,字符串属于基础类型,若未手动配置该参数的注入逻辑,容器无法自动提供对应的连接字符串值。 - 未注册构造函数中的其他依赖服务:如果
IPrintExceptions、IGetPropertiesService、ISQLParametersService、ISerializeService、IDeserealizeService<T>这些接口的实现类未在Program.cs中注册到DI容器,容器无法构造Select<Period>实例。 - 泛型服务注册不规范:若
IDeserealizeService<T>是泛型接口,需以开放泛型方式注册(如AddTransient(typeof(IDeserealizeService<>), typeof(DeserealizeService<>))),仅注册特定泛型参数的版本会导致容器无法匹配对应类型。
解决方向
处理
_connection字符串参数:- 从配置文件读取连接字符串,通过工厂方法手动注入:
var connectionString = builder.Configuration.GetConnectionString("YourConnectionName"); builder.Services.AddTransient<IDBActionQuery<Period>>(sp => new Select<Period>( connectionString, sp.GetRequiredService<IPrintExceptions>(), sp.GetRequiredService<IGetPropertiesService>(), sp.GetRequiredService<ISQLParametersService>(), sp.GetRequiredService<ISerializeService>(), sp.GetRequiredService<IDeserealizeService<Period>>() ) ); - 或者将连接字符串注册为单例服务:
builder.Services.AddSingleton(builder.Configuration.GetConnectionString("YourConnectionName"));
- 从配置文件读取连接字符串,通过工厂方法手动注入:
注册所有依赖服务:确保构造函数中用到的每个接口都已在DI容器中注册,示例代码:
builder.Services.AddTransient<IPrintExceptions, PrintExceptions>(); builder.Services.AddTransient<IGetPropertiesService, GetPropertiesService>(); builder.Services.AddTransient<ISQLParametersService, SQLParametersService>(); builder.Services.AddTransient<ISerializeService, SerializeService>(); builder.Services.AddTransient(typeof(IDeserealizeService<>), typeof(DeserealizeService<>));
内容的提问来源于stack exchange,提问作者sofnomic cr
相关产品推荐
相关产品推荐

