Внедрить 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
}
}