0

I am trying to build a mediator pipeline with Mediatr and Autofac but am struggling to resolve a collection of validators from 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:

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.

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!

  • Have you checked to see that your filtering logic actually returns the types you expect? In your second alternative, you can debug and see that the foreach loop does, in fact, go over all the types you expect? Just to make sure the problem is with the Autofac registration, not the type query. – Avner Shahar-Kashtan Nov 13 '16 at 11:07

1 Answers1

0

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:

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");
Mickaël Derriey
  • 12,796
  • 1
  • 53
  • 57