У меня есть следующие классы репозитория:

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 в моем Startup.cs?

Я реализовал это так:

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

Но затем я получаю следующую ошибку:

Невозможно создать экземпляр типа реализации 'Test.Domain.Repository 1[T]' for service type 'Test.Domain.IRepository 1 [T]'.

16
Palmi 4 Сен 2016 в 21:37

3 ответа

Лучший ответ

Repository<T> - это абстрактный класс, поэтому вы не можете зарегистрировать его как реализацию, потому что абстрактный класс просто не может быть создан. Ваша регистрация прошла бы нормально, если бы Repository<T> не было абстрактным.

Если вы не можете сделать класс репозитория неабстрактным, вы можете зарегистрировать конкретную реализацию вашего класса репозитория:

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

Это будет правильно вводить зависимости вашего контроллера.

20
dotnetom 4 Сен 2016 в 18:51

Я знаю, что это очень поздно, но я публикую здесь свое решение, чтобы другие могли ссылаться на него и использовать его. Я написал несколько расширений для регистрации всех производных типов универсального интерфейса.

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 < / a> репозиторий.

7
Arul 21 Июн 2019 в 12:15

Вы можете зарегистрировать абстрактный класс только как службу , а не как реализацию , как сказал @dotnetom.

См. Определения ниже

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

IMHO, я предпочитаю использовать определения интерфейсов, а не абстрактные классы.

-1
sta 28 Июл 2020 в 07:49