使用Autofac解决IEnumerable问题

问题描述:

我正在尝试使用Mediatr和Autofac构建中介管道,但我正努力从Autofac解析验证程序集合。使用Autofac解决IEnumerable问题

public class MediatorPipeline<TRequest, TResponse> 
    : IAsyncRequestHandler<TRequest, TResponse> where TRequest : IAsyncRequest<TResponse> 
{ 
    private readonly IAsyncRequestHandler<TRequest, TResponse> _inner; 
    private readonly IEnumerable<IValidator<TRequest>> _validators; 

    public MediatorPipeline(IAsyncRequestHandler<TRequest, TResponse> inner, 
     IEnumerable<IValidator<TRequest>> validators) 
    { 
     _inner = inner; 
     _validators = validators; 
    } 
    ... 
} 

当我把IValidator<TRequest>它解决了精细构造,但是当我把IEnumerable<IValidator<TRequest>>失败,例外:

容器或服务定位器配置不正确,或处理不与容器注册。 ---> Autofac.Core.DependencyResolutionException:激活特定注册期间发生错误。

这里是我的注册代码:

builder.RegisterAssemblyTypes(assembly) 
    .Where(t => t.IsClosedTypeOf(typeof(IValidator<>))) 
    .AsImplementedInterfaces() 
    .InstancePerLifetimeScope(); 

我有这个替代的定位相同的结果:

var openGenericType = typeof(IValidator<>); 

var query = from type in assembly.GetTypes().Where(c => !(c.GetTypeInfo().IsAbstract || c.GetTypeInfo().IsGenericTypeDefinition)) 
      let interfaces = type.GetInterfaces() 
      let genericInterfaces = interfaces.Where(i => i.GetTypeInfo().IsGenericType && i.GetGenericTypeDefinition() == openGenericType) 
      let matchingInterface = genericInterfaces.FirstOrDefault() 
      where matchingInterface != null 
      select new { matchingInterface, type }; 

foreach (var pair in query) 
{ 
    builder.RegisterType(pair.type).As(pair.matchingInterface); 
} 

任何建议非常感谢!

+0

你检查,看看你的过滤逻辑实际上返回你所期望的类型?在第二种选择中,您可以调试并查看foreach循环确实会覆盖您期望的所有类型? 只是为了确保问题出现在Autofac注册中,而不是类型查询。 –

首先,很高兴看到整个异常(包含内部异常) - 堆栈跟踪。

Autofac暴露了一个方便的扩展方法,AsClosedTypesOf,你可以用这样的方式:

builder 
    .RegisterAssemblyTypes(ThisAssembly) 
    .AsClosedTypesOf(typeof(IValidator<>)) 
    .InstancePerLifetimeScope(); 

这将做的工作给你,让你不必进入深刻的反思注册您的验证。

然后,您需要注册您的处理程序,并在它们上面的装饰:

builder 
    .RegisterAssemblyTypes(ThisAssembly) 
    .AsClosedTypesOf(typeof(IAsyncRequestHandler<,>), "base-handler") 
    .InstancePerDependency(); 

builder.RegisterGenericDecorator(
    typeof(MediatorPipeline<,>), 
    typeof(IAsyncRequestHandler<,>), 
    "base-handler");