关于C#:如何在ASP.NET Core中注入泛型的依赖项

How to inject dependencies of generics in ASP.NET Core

我有以下存储库类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class TestRepository : Repository<Test>
{
    private TestContext _context;

    public TestRepository(TestContext context) : base(context)
    {
        _context = context;
    }
}

public abstract class Repository< T > : IRepository< T > where T : Entity
{
    private TestContext _context;

    public Repository(TestContext context)
    {
        _context = context;
    }
    ...
}

public interface IRepository< T >    
{
    ...
}

如何在Startup.cs中的ASP.NET Core中实现依赖项注入?

我是这样实现的:

1
services.AddScoped(typeof(IRepository<>), typeof(Repository<>));

但是然后我得到以下错误:

Cannot instantiate implementation type 'Test.Domain.Repository1[T]'
for service type 'Test.Domain.IRepository
1[T]'.


Repository< T >是抽象类,因此您无法将其注册为实现,因为抽象类根本无法实例化。 如果Repository< T >不是抽象的,则您的注册将正常进行。

如果不能使存储库类成为非抽象类,则可以注册存储库类的特定实现:

1
services.AddScoped(typeof(IRepository<Test>), typeof(TestRepository));

这将正确注入依赖项到您的控制器。


我知道这很晚了,但是我在这里发布了我的解决方案,以便其他人可以参考和使用它。 我已经写了一些扩展来注册通用接口的所有派生类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
public static List<TypeInfo> GetTypesAssignableTo(this Assembly assembly, Type compareType)
{
        var typeInfoList = assembly.DefinedTypes.Where(x => x.IsClass
                            && !x.IsAbstract
                            && x != compareType
                            && x.GetInterfaces()
                                    .Any(i => i.IsGenericType
                                            && i.GetGenericTypeDefinition() == compareType))?.ToList();

        return typeInfoList;
 }

public static void AddClassesAsImplementedInterface(
        this IServiceCollection services,
        Assembly assembly,
        Type compareType,
        ServiceLifetime lifetime = ServiceLifetime.Scoped)
 {
        assembly.GetTypesAssignableTo(compareType).ForEach((type) =>
        {
            foreach (var implementedInterface in type.ImplementedInterfaces)
            {
                switch (lifetime)
                {
                    case ServiceLifetime.Scoped:
                        services.AddScoped(implementedInterface, type);
                        break;
                    case ServiceLifetime.Singleton:
                        services.AddSingleton(implementedInterface, type);
                        break;
                    case ServiceLifetime.Transient:
                        services.AddTransient(implementedInterface, type);
                        break;
                }
            }
        });
}

在启动类中,您只需注册您的通用接口,如下所示。

1
services.AddClassesAsImplementedInterface(Assembly.GetEntryAssembly(), typeof(IRepository<>));

您可以在此Github存储库中找到完整的扩展代码。