2016-07-09 11 views
2

Ich versuche, eine ASP.NET Core-Anwendung mit CQRS-Muster einzurichten. Um dies zu erreichen, ich diese Bibliotheken verwende:FluentValidation Decorator funktioniert nicht mit Autofac und Mediator

"Autofac.Extensions.DependencyInjection": "4.0.0-rc3-280", 
"FluentValidation": "6.4.0-beta3", 
"MediatR": "2.1.0" 

ich alle erforderlichen Einstellungen haben, Mediatr arbeitet, Dependency Injection funktioniert jedoch nicht mein Code nicht durch Validierung passieren, bevor an den Handler gehen. Ich glaube, ich habe ein Problem mit der Registrierung der Validierung Dekorator. Da die meisten Bibliotheken, die ich verwende, kürzlich aktualisiert und sehr geändert wurden, um ASP.NET Core zu unterstützen. Was fehlt mir bei der Konfiguration? Wie es sein sollte?

Meine Konfiguration

public IServiceProvider ConfigureServices(IServiceCollection services) 
    { 

     var builder = new ContainerBuilder(); 
     builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces(); 
     builder.RegisterAssemblyTypes(typeof(GetUserByEmailQuery).GetTypeInfo().Assembly).AsImplementedInterfaces(); 

     builder.Register<SingleInstanceFactory>(ctx => 
     { 
      var c = ctx.Resolve<IComponentContext>(); 
      return t => c.Resolve(t); 
     }); 
     builder.Register<MultiInstanceFactory>(ctx => 
     { 
      var c = ctx.Resolve<IComponentContext>(); 
      return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t)); 
     }); 


     builder.RegisterGenericDecorator(
      typeof(MediatorPipeline<,>), 
      typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator") 
      .Keyed("MediatorPipeline", typeof(IRequestHandler<,>)) 
      .InstancePerLifetimeScope(); 


     //register validator decorator 
     builder.RegisterGenericDecorator(
      typeof(ValidatorHandler<,>), 
      typeof(IRequestHandler<,>), 
      "Validator") 
      .InstancePerLifetimeScope(); 


     builder.Populate(services); 
     var container = builder.Build(); 

     return container.Resolve<IServiceProvider>(); 
    } 

MediatorPipeline (nicht sicher, ob ich es wirklich brauchen.)

public class MediatorPipeline<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse> 
{ 

    private readonly IRequestHandler<TRequest, TResponse> _inner; 
    private readonly IPreRequestHandler<TRequest>[] _preRequestHandlers; 
    private readonly IPostRequestHandler<TRequest, TResponse>[] _postRequestHandlers; 

    public MediatorPipeline(IRequestHandler<TRequest, TResponse> inner, IPreRequestHandler<TRequest>[] preRequestHandlers, IPostRequestHandler<TRequest, TResponse>[] postRequestHandlers) 
    { 
     _inner = inner; 
     _preRequestHandlers = preRequestHandlers; 
     _postRequestHandlers = postRequestHandlers; 
    } 

    public TResponse Handle(TRequest message) 
    { 

     foreach (var preRequestHandler in _preRequestHandlers) 
     { 
      preRequestHandler.Handle(message); 
     } 

     var result = _inner.Handle(message); 

     foreach (var postRequestHandler in _postRequestHandlers) 
     { 
      postRequestHandler.Handle(message, result); 
     } 

     return result; 
    } 
} 

ValidatorHandler

public class ValidatorHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse> 
{ 

    private readonly IRequestHandler<TRequest, TResponse> _inner; 
    private readonly IValidator<TRequest>[] _validators; 

    public ValidatorHandler(IRequestHandler<TRequest, TResponse> inner, IValidator<TRequest>[] validators) 
    { 
     _inner = inner; 
     _validators = validators; 
    } 

    public TResponse Handle(TRequest message) 
    { 
     var context = new ValidationContext(message); 

     var failures = _validators 
      .Select(v => v.Validate(context)) 
      .SelectMany(result => result.Errors) 
      .Where(f => f != null) 
      .ToList(); 

     if (failures.Any()) 
      throw new ValidationException(failures); 

     return _inner.Handle(message); 
    } 
} 

GetUserByEmailQuery.cs

public class GetUserByEmailQuery : IRequest<UserDomain> 
{ 
    public string UserEmail { get; set; } 
} 

public class GetUserByEmailQueryValidator : AbstractValidator<GetUserByEmailQuery> 
{ 
    public GetUserByEmailQueryValidator() 
    { 
     RuleFor(q => q.UserEmail).NotNull().WithMessage("Email alanı boş bırakılamaz!"); 
    } 
    public bool Handle(GetUserByEmailQuery message) 
    { 

     return true; 
    } 
} 
public class GetUserByEmailQueryHandler : IRequestHandler<GetUserByEmailQuery, UserDomain> 
{ 
    private readonly AuthDbContext _context; 

    public GetUserByEmailQueryHandler(AuthDbContext context) 
    { 
     _context = context; 
    } 

    public UserDomain Handle(GetUserByEmailQuery message) 
    { 
     var authUser = _context.Users.Where(x => x.Email.Equals(message.UserEmail)).Include(y => y.UserMeta).Include(z => z.UserRole).FirstOrDefault(); 
      var userDomain = Mapper.Map<UserDomain>(authUser); 
      return userDomain; 


    } 
} 

in dieser Klasse geht mein Code direkt in public UserDomain Handle(GetUserByEmailQuery message), ohne Validierung zu tun.

+0

Wenn Sie einen Anforderungshandler ** manuell auflösen ** Hat es den Dekorator? –

Antwort

1

Das Problem liegt in dieser Zeile:

typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator") 

Es hat keinen handler Schlüssel finden können.
Also habe ich die Registrierung der Typen aufgeteilt, indem zuerst alle Typen in Ihrer Assembly registriert werden, aber die RequestHandler ausgeschlossen werden. Und dann registriert die RequestHandlers mit einem Schlüssel handler.

public IServiceProvider ConfigureServices(IServiceCollection services) 
{ 

    var builder = new ContainerBuilder(); 
    builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces(); 
    builder.RegisterAssemblyTypes(typeof(GetUserByEmailQuery).GetTypeInfo().Assembly) 
      .Where(t => !t.IsClosedTypeOf(typeof(IRequestHandler<,>))) 
      .AsImplementedInterfaces(); 

    builder.Register<SingleInstanceFactory>(ctx => 
    { 
     var c = ctx.Resolve<IComponentContext>(); 
     return t => c.Resolve(t); 
    }); 
    builder.Register<MultiInstanceFactory>(ctx => 
    { 
     var c = ctx.Resolve<IComponentContext>(); 
     return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t)); 
    }); 

    builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly()) 
      .As(type => type.GetInterfaces() 
       .Where(interfaceType => interfaceType.IsClosedTypeOf(typeof(IRequestHandler<,>))) 
       .Select(interfaceType => new KeyedService("handler", interfaceType))) 
      .InstancePerLifetimeScope(); 

    builder.RegisterGenericDecorator(
     typeof(MediatorPipeline<,>), 
     typeof(IRequestHandler<,>), fromKey: "handler", toKey: "Validator") 
     .Keyed("MediatorPipeline", typeof(IRequestHandler<,>)) 
     .InstancePerLifetimeScope(); 

    //register validator decorator 
    builder.RegisterGenericDecorator(
     typeof(ValidatorHandler<,>), 
     typeof(IRequestHandler<,>), 
     "Validator") 
     .InstancePerLifetimeScope(); 


    builder.Populate(services); 
    var container = builder.Build(); 

    return container.Resolve<IServiceProvider>(); 
} 

Hoffe, das hilft!

Verwandte Themen