如何使用点网核心IService集合注入多个通用接口依赖项

问题描述

我们具有以下层次结构

public class ProviderResponse
{
    public string Prop {get; set;}
}

public class Provider1Response: ProviderResponse
{
    public string Prop1 {get; set;}
}
public class Provider2Response: ProviderResponse
{
    public string Prop2 {get; set;}
}

此处ProviderResponse是包含通用属性的基类,并且还有其他一些扩展。

然后我们有逻辑类

public interface IProviderResponseLogic<T> where T:ProviderResponse
{
   bool Process<T>(T t);
}

public class Provider1ResponseLogic : IProviderResponseLogic<Provider1Response>
{
    public bool Process(Provider1Response resp)
    {
        //logic
    }
}

public class Provider2ResponseLogic : IProviderResponseLogic<Provider2Response>
{
    public bool Process(Provider2Response resp)
    {
        //logic
    }
}

我需要有条件地在控制器类中注入特定的逻辑实现。在我的Action方法中,我有一个输入参数枚举(Provider),它将决定要调用的具体逻辑。

我通过这样创建Func<Provider,IProviderResponseLogic<T>尝试了工厂方法注入

services.AddTransient<Provider1ResponseLogic>();
services.AddTransient<Provider2ResponseLogic>();
services.AddTransient<Func<Provider,IProviderResponseLogic<ProviderResponse>>>(serviceProvider => key =>
             {
                 return key switch
                 {
                     Provider.Provider1 => serviceProvider.GetService<Provider1ResponseLogic>()
                     Provider.Provider2 => serviceProvider.GetService<Provider2ResponseLogic>()
                     _ => null,//key not found
                 };
             });

出现以下错误

Cannot implicitly convert type 'Provider1ResponseLogic' to 'IProviderResponseLogic<ProviderResponse>'

基本上,它不会返回更多派生的类型。

这是怎么了?我该如何解决

我也可以通过services.AddTransient<IProviderResponseLogic<Provider1ResponseLogic>,Provider1ResponseLogic>();之类的接口注册每个实现 并将每一个注入控制器,但是我认为如果实现类增加,这是否会失控。

解决方法

尽管Provider1Response继承自ProviderResponse,但这并不意味着IProviderResponseLogic<Provider1Response>可以转换为IProviderResponseLogic<ProviderResponse>。仅当基本接口的类型参数为covariant时,才能进行此转换。但这似乎并不适合解决您的问题,因为您打算在相反的位置使用类型参数T

我也可以在接口上注册每个实现,并将每个实现注入到控制器中,但是我认为如果实现类增加,它是否会失控。

我认为这是唯一好的解决方案。当您添加更多实现时,切换案例也将“失去控制”。