使用 mediatR 管道行为添加验证
Adding validation using mediatR pipeline behaviour
作为管道行为的一部分,尝试在创建客户时设置验证
public class ValidationBehavoir<TRequest, TResponse> : IPipelineBehavior<TRequest, TRequest>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TRequest> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TRequest> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if(failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
这里是设置DI时添加的服务
services.AddMediatR(typeof(Program));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavoir<,>));
services.AddMediatR(typeof(CreateCustomerCommand).GetTypeInfo().Assembly);
services.AddMediatR(typeof(GetCustomersQuery).GetTypeInfo().Assembly);
But still, getting below error?
System.ArgumentException: Implementation type 'CustomerApis.PipelineBehaviors.ValidationBehavoir`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]' can't be converted to service type 'MediatR.IPipelineBehavior`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]'
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite..ctor(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.<>c__DisplayClass7_0.<GetCallSite>b__0(Type type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
有人可以帮我吗?
您这边可能缺少一些信息(例如每个实体的特定验证器)但是,我会将 services.AddTransient 行移到其他行下方,或者我会尝试使用此行代替您拥有的行:
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavoir<,>));
public class 验证行为:IPipelineBehavior
其中 TRequest : IRequest
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
到
public class 验证行为:IPipelineBehavior
其中 TRequest : IRequest
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
这个解决方案适合我。
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly(), ServiceLifetime.Transient);
作为管道行为的一部分,尝试在创建客户时设置验证
public class ValidationBehavoir<TRequest, TResponse> : IPipelineBehavior<TRequest, TRequest>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TRequest> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TRequest> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if(failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
这里是设置DI时添加的服务
services.AddMediatR(typeof(Program));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavoir<,>));
services.AddMediatR(typeof(CreateCustomerCommand).GetTypeInfo().Assembly);
services.AddMediatR(typeof(GetCustomersQuery).GetTypeInfo().Assembly);
But still, getting below error?
System.ArgumentException: Implementation type 'CustomerApis.PipelineBehaviors.ValidationBehavoir`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]' can't be converted to service type 'MediatR.IPipelineBehavior`2[Customers.Service.Command.CreateCustomerCommand,Customers.Domain.Entities.Customer]'
at Microsoft.Extensions.DependencyInjection.ServiceLookup.ConstructorCallSite..ctor(ResultCache cache, Type serviceType, ConstructorInfo constructorInfo, ServiceCallSite[] parameterCallSites)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateConstructorCallSite(ResultCache lifetime, Type serviceType, Type implementationType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateOpenGeneric(ServiceDescriptor descriptor, Type serviceType, CallSiteChain callSiteChain, Int32 slot)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.TryCreateEnumerable(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.CreateCallSite(Type serviceType, CallSiteChain callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.CallSiteFactory.<>c__DisplayClass7_0.<GetCallSite>b__0(Type type)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
有人可以帮我吗?
您这边可能缺少一些信息(例如每个实体的特定验证器)但是,我会将 services.AddTransient 行移到其他行下方,或者我会尝试使用此行代替您拥有的行:
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly());
services.AddMediatR(Assembly.GetExecutingAssembly());
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavoir<,>));
public class 验证行为:IPipelineBehavior 其中 TRequest : IRequest {
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
到
public class 验证行为:IPipelineBehavior 其中 TRequest : IRequest {
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationBehavoir(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators.Select(x => x.Validate(context)).SelectMany(x => x.Errors).ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
return await next();
}
}
这个解决方案适合我。
services.AddValidatorsFromAssembly(Assembly.GetExecutingAssembly(), ServiceLifetime.Transient);