如何注册可注入为ISpecificApi<IDetail>的SpecificApi服务?
泛型依赖注入问题解决方案
你遇到的核心问题是泛型接口缺乏协变支持,导致SpecificApi(实现ISpecificApi<SpecificDetail>)无法被注入到依赖ISpecificApi<IDetail>的Consumer中。
步骤1:修改泛型接口以支持协变
由于TDetail仅出现在方法的返回值位置(输出位置),我们可以给泛型接口添加out关键字标记协变,这样子类泛型类型可以向上转换为父类泛型类型:
public interface IBaseApi<out TDetail> where TDetail : IDetail { TDetail Method1(); } public interface ISpecificApi<out TDetail> : IBaseApi<TDetail> where TDetail : IDetail { }
步骤2:正确注册服务
现在有两种可行的注册方式:
方式一:直接注册目标服务类型
直接将ISpecificApi<IDetail>映射到SpecificApi实例,利用协变完成类型转换:
builder.Services.AddSingleton<ISpecificApi<IDetail>>(sp => new SpecificApi()); builder.Services.AddSingleton<Consumer>();
方式二:先注册具体泛型服务,再映射到目标类型
先注册ISpecificApi<SpecificDetail>,再通过容器获取该实例并转换为ISpecificApi<IDetail>:
builder.Services.AddSingleton<ISpecificApi<SpecificDetail>, SpecificApi>(); builder.Services.AddSingleton<ISpecificApi<IDetail>>(sp => sp.GetRequiredService<ISpecificApi<SpecificDetail>>()); builder.Services.AddSingleton<Consumer>();
原注册方式失败原因解析
- 开放泛型注册失败:
builder.Services.AddSingleton(typeof(ISpecificApi<>), typeof(SpecificApi))报错,是因为SpecificApi是封闭泛型实现(绑定了SpecificDetail),而ISpecificApi<>是开放泛型,DI要求开放泛型服务必须对应开放泛型实现类。 - 编译错误:
builder.Services.AddSingleton<ISpecificApi<IDetail>, SpecificApi>无法编译,是因为未标记协变时,ISpecificApi<SpecificDetail>与ISpecificApi<IDetail>之间没有隐式转换关系。 - 类型不匹配:
builder.Services.AddSingleton<ISpecificApi<SpecificDetail>, SpecificApi>可以运行,但Consumer依赖的是ISpecificApi<IDetail>,类型不匹配导致无法注入。
内容的提问来源于stack exchange,提问作者NSouth
相关产品推荐
相关产品推荐

