Внедрить IEnumerable универсального интерфейса в Unity Dependency Injection C#

Я работаю над приложением web API 2 и использую внедрение зависимостей Unity.

У меня есть несколько типов фильтров: имя, марка, типы...

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

интерфейс:

public interface IFilterService<T>
{
    bool CanHandle(FilterType type);

    Task<ServiceResult<T>> FilterAsync(T entity);
}

и классы такие:

public class NameService : IFilterService<Name>
{
    public bool CanHandle(FacetType type)
    {
        return type == FacetType.Name;
    }

    public async Task<ServiceResult<Name>> FilterAsync(Name entity)
    {
      // Code
    }
}

контроллер похож на:

public class FilterController
{
    private readonly IEnumerable<IFilterService> filters;

    public MediaController(IEnumerable<IFilterService> filters)
    {
        this.filters = filters;
    }

     public async Task<HttpResponseMessage> FilterAsync(FilterType type, Name entity)
     {
        foreach(var filter in this.filters.Where(x => x.CanHandle(type)))
        {
            filter.FilterAsync(entity); 
        }
        ....
    }
}

все работает правильно: единственная проблема - регистрация интерфейса и классов в Unity Dependency Injection.

container.RegisterType<IEnumerable<IFilterService>, IFilterService[] >(
                new ContainerControlledLifetimeManager());
container.RegisterType<IFilterService, NameService>("Name Service",
                new ContainerControlledLifetimeManager());

Я получаю эту ошибку:

Ошибка CS0305 Для использования универсального типа 'IFilterService' требуются аргументы 1 типа

Тот же код, который я пробовал, но с не универсальным интерфейсом и работает нормально.

как исправить ошибку? и небольшое объяснение может быть очень полезным. благодарю вас.

1 ответ

Решение

У вас есть два варианта, во-первых, чтобы зарегистрировать определенный тип фильтра

container.RegisterType<IEnumerable<IFilterService<Name>>, IFilterService<Name>[] >(
                new ContainerControlledLifetimeManager());
container.RegisterType<IFilterService<Name>, NameService>("Name Service",
                new ContainerControlledLifetimeManager());

Используется как

public class FilterController
{
    private readonly IEnumerable<IFilterService<Name>> filters;

    public MediaController(IEnumerable<IFilterService<Name>> filters)
    {
        this.filters = filters;
    }

     public async Task<HttpResponseMessage> FilterAsync(FilterType type, Name entity)
     {
        foreach(var filter in this.filters.Where(x => x.CanHandle(type)))
        {
            filter.FilterAsync(entity); 
        }
        ....
    }
}

Второй вариант - сделать ваш интерфейс не универсальным, но вы оставите функцию универсальной

public interface IFilterService
{
    bool CanHandle(FilterType type);

    Task<ServiceResult<T>> FilterAsync<T>(T entity);
}

public class NameService : IFilterService
{
    public bool CanHandle(FacetType type)
    {
        return type == FacetType.Name;
    }

    public Task<ServiceResult<T>> FilterAsync<T>(T entity)
    {
      if(!entity is Name)
          throw new NotSupportedException("The parameter 'entity' is not assignable to the type 'Name'");

        return FilterAsyncInternal((Name)entity);
    }

    private async Task<ServiceResult<Name>> FilterAsyncInternal(Name entity)
    {
        //code
    }
}
Другие вопросы по тегам