在 C# 中,如何使用泛型基类将泛型接口的所有实例注入到单个构造函数中?

Rya*_*ion 6 .net c# generics dependency-injection interface

我定义了以下接口:

public interface ICustomService<T> where T : CustomObject
{
   IEnumerable<T> GetById(int Id);
   ...
}
Run Code Online (Sandbox Code Playgroud)

它的 2 个实现,其中MyObject1&MyObject2都继承自CustomObject

public class CustomService1 : ICustomService<MyObject1>
{
    public IEnumerable<MyObject1> GetById(int Id)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)
public class CustomService2 : ICustomService<MyObject2>
{
    public IEnumerable<MyObject2> GetById(int Id)
    {
        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

我尝试将这两个注册为ICustomService<CustomObject>但收到错误:

没有从“CustomerService1”到“ICustomService<CustomObject>”的隐式引用转换

相反,像这样注册:

services.AddTransient<ICustomService<MyObject1>, CustomService1>();
services.AddTransient<ICustomService<MyObject2>, CustomService2>();
Run Code Online (Sandbox Code Playgroud)

当像上面那样注册时,我的 IEnumerableservices是空的:

public ThirdService(IEnumerable<ICustomService<CustomObject>> services)
{
    
}
Run Code Online (Sandbox Code Playgroud)

如何将所有实现注入ICustomServiceThirdService

我正在尝试这样做,以便ThirdService可以给定一个 ID,然后在所有服务上CustomObject使用该 ID来获取所有内容。GetById

Joh*_*lay 5

假设没有其他具有 type 参数T、 type 可变属性的接口方法,或者返回以非协变方式T使用的泛型类型的方法,您可以使用以下方法使该协变:TTout

public interface ICustomService<out T> where T : CustomObject
Run Code Online (Sandbox Code Playgroud)

这将使您的注册尝试有效:

services.AddTransient<ICustomService<CustomObject>, CustomService1>();
services.AddTransient<ICustomService<CustomObject>, CustomService2>();
Run Code Online (Sandbox Code Playgroud)

协方差确保 和CustomService1可以CustomService2安全地用来代替 a ICustomService<CustomObject>,尽管它们都将 的子类声明MyObject为通用参数。