简体   繁体   English

使用Autofac解决IEnumerable

[英]Resolve IEnumerable with Autofac

I am trying to build a mediator pipeline with Mediatr and Autofac but am struggling to resolve a collection of validators from Autofac. 我正在尝试使用Mediatr和Autofac构建中介程序管道,但正在努力解决Autofac的验证程序集合。

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;
    }
    ...
}

When I put IValidator<TRequest> in the constructor it resolves fine, but when I put IEnumerable<IValidator<TRequest>> it fails, with the exception: 当我在构造函数中放入IValidator<TRequest>时,它可以很好地解决,但是当我将IEnumerable<IValidator<TRequest>>放入时,它会失败,但以下情况除外:

Container or service locator not configured properly or handlers not registered with your container. 容器或服务定位器配置不正确,或者处理程序未在容器中注册。 ---> Autofac.Core.DependencyResolutionException: An error occurred during the activation of a particular registration. ---> Autofac.Core.DependencyResolutionException:激活特定注册期间发生错误。

Here is my registration code: 这是我的注册码:

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

I had the same result with this alternative registration: 使用此替代注册,我得到了相同的结果:

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

Any suggestions much appreciated! 任何建议,不胜感激!

First, it would be nice to see the whole exception - inner exception included - with the stack trace. 首先,很高兴看到整个异常(包括内部异常)与堆栈跟踪。

Autofac exposes a handy extension method, AsClosedTypesOf , which you can use this way: Autofac公开了一个方便的扩展方法AsClosedTypesOf ,您可以使用以下方式:

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

This will do the work for you so you don't have to go into deep reflection to register your validators. 这将为您完成工作,因此您无需深入思考即可注册验证器。

You then need to register your handlers and the decorator on top of them: 然后,您需要在它们之上注册处理程序和装饰器:

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM