如何在ASP中注入泛型的依赖.净的核心

本文关键字:依赖 核心 泛型 注入 ASP | 更新日期: 2023-09-27 18:05:32

我有以下存储库类:

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>    
{
    ...
}

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

我是这样实现的:

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

但是我得到以下错误:

无法实例化实现类型"Test.Domain.Repository 1[T]' for service type 'Test.Domain.IRepository 1[T]"。

如何在ASP中注入泛型的依赖.净的核心

Repository<T>是一个抽象类,所以你不能将它注册为一个实现,因为抽象类根本不能被实例化。如果Repository<T>不是抽象的,您的注册将正常工作。

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

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

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

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;
                }
            }
        });
}

在启动类中,你只需像下面这样注册你的通用接口。

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

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

抽象类只能注册为服务,不能注册为实现

参见下面的定义

 public abstract class BaseClass<T>
{
    public BaseClass()
    {
    }
}
public class DerivedClass : BaseClass<Entity>
{
    public DerivedClass() : base() { }
}
public class DerivedClass2<T> : BaseClass<T> where T: Entity
{
   
}
public class Entity
{
}

控制器:

public class WeatherForecastController : ControllerBase
    {
        ......
        public WeatherForecastController(BaseClass<Entity> baseClass)
        {
            
        }
         ...
}

如果你以这种方式注入它们:

 services.AddScoped(typeof(BaseClass<>), typeof(DerivedClass));

当你解决依赖时,你会得到这个错误:

开放泛型服务类型'BaseClass ' 1[T]'需要注册一个开放泛型实现类型。(参数描述符)

你应该注册泛型类型,或者用定义的泛型参数注册服务和实现

现在这个应该也可以正常工作了

services.AddScoped(typeof(BaseClass<>), typeof(DerivedClass2<>));

services.AddScoped(typeof(BaseClass<Entity>), typeof(DerivedClass2<Entity>));

我更喜欢接口定义,而不是抽象类。