【问题标题】:Inject an IEnumerable of generic interface in Unity Dependency Injection c#在 Unity Dependency Injection c# 中注入通用接口的 IEnumerable
【发布时间】:2017-07-14 18:34:16
【问题描述】:

我正在开发一个 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 依赖注入中注册接口和类。

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

我收到此错误:

错误 CS0305 使用泛型类型“IFilterService”需要 1 种类型 论据

我已经尝试过相同的代码,但使用非通用接口并且工作正常。

如何修复错误?一点解释可能非常有用。谢谢。

【问题讨论】:

    标签: c# dependency-injection generic-interface


    【解决方案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
        }
    }
    

    【讨论】:

    • 第二种方案的返回值是多少?
    • 从您的示例控制器返回一个 Task&lt;ServiceResult&lt;Name&gt;&gt;Task&lt;ServiceResult&lt;T&gt;&gt; 中的 T 将是 entity 的任何类型。
    • 我更新了第二个示例,通过将其拆分为两个函数来更清楚地了解将返回的内容。
    • 错误 CS0029 无法将类型“Bms.Domain.Services.ServiceResult”隐式转换为“Bms.Domain.Services.ServiceResult”名称名称 = 实体为姓名; return await this.FilterAsyncInternal(name);
    • 成功了,返回值被转换为ServiceResult:return await this.FilterAsyncInternal(manufacturer) as ServiceResult;
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    • 1970-01-01
    相关资源
    最近更新 更多