2016-07-09 1 views
2

J'essaie de configurer une application ASP.NET Core avec un modèle CQRS. Pour aider à atteindre ce que je utilise ces bibliothèques:Le décorateur FluentValidation ne fonctionne pas avec autofac et mediator

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

Je ne tous les paramètres requis, Mediatr fonctionne, les travaux d'injection de dépendance, cependant, mon code ne passe pas par la validation avant d'aller au gestionnaire. Je pense que j'ai un problème avec l'enregistrement du décorateur de validation. Étant donné que la plupart des bibliothèques que j'utilise sont récemment mises à jour et beaucoup modifiées afin de prendre en charge ASP.NET Core. Qu'est-ce qui me manque dans la configuration? Comment ça devrait être?

Ma configuration

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 (Je ne sais pas si je vraiment besoin.)

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; 


    } 
} 

dans cette classe mon code va directement dans public UserDomain Handle(GetUserByEmailQuery message) sans faire de validation.

+0

Si vous résolvez un gestionnaire de requêtes ** manuellement ** at-il le décorateur? –

Répondre

1

Le problème se trouve dans cette ligne:

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

Il ne peut pas trouver une clé handler.
Je divise donc l'enregistrement des types en enregistrant d'abord tous les types dans votre assembly mais en excluant RequestHandlers. Et puis enregistré les RequestHandlers avec une clé 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>(); 
} 

Espérons que cela aide!