using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using Autofac; using Autofac.Core; using Autofac.Features.Variance; using CQRS_Simple.API.PipelineBehaviors; using FluentValidation; using MediatR; using MediatR.Pipeline; namespace CQRS_Simple.API.Modules { public class MediatorModule : Autofac.Module { protected override void Load(ContainerBuilder builder) { builder.RegisterSource(new ScopedContravariantRegistrationSource( typeof(IRequestHandler<,>), typeof(INotificationHandler<>), typeof(IValidator<>) )); builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces(); var mediatrOpenTypes = new[] { typeof(IRequestHandler<,>), typeof(INotificationHandler<>), typeof(IValidator<>), }; foreach (var mediatrOpenType in mediatrOpenTypes) { builder .RegisterAssemblyTypes(typeof(Startup).GetTypeInfo().Assembly) .AsClosedTypesOf(mediatrOpenType) .AsImplementedInterfaces(); } builder.RegisterGeneric(typeof(RequestPostProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>)); builder.RegisterGeneric(typeof(RequestPreProcessorBehavior<,>)).As(typeof(IPipelineBehavior<,>)); //Mediator validation Pipeline builder.RegisterGeneric(typeof(ValidationBehavior<,>)).As(typeof(IPipelineBehavior<,>)); builder.Register(ctx => { var c = ctx.Resolve(); return t => c.Resolve(t); }); // builder.RegisterGeneric(typeof(CommandValidationBehavior<,>)).As(typeof(IPipelineBehavior<,>)); } public class ScopedContravariantRegistrationSource : IRegistrationSource { private readonly IRegistrationSource _source = new ContravariantRegistrationSource(); private readonly List _types = new List(); public ScopedContravariantRegistrationSource(params Type[] types) { if (types == null) throw new ArgumentNullException(nameof(types)); if (!types.All(x => x.IsGenericTypeDefinition)) throw new ArgumentException("Supplied types should be generic type definitions"); _types.AddRange(types); } public IEnumerable RegistrationsFor(Service service, Func> registrationAccessor) { var components = _source.RegistrationsFor(service, registrationAccessor); foreach (var c in components) { var defs = c.Target.Services .OfType() .Select(x => x.ServiceType.GetGenericTypeDefinition()); if (defs.Any(_types.Contains)) yield return c; } } public bool IsAdapterForIndividualComponents => _source.IsAdapterForIndividualComponents; } } }