2017-02-16 23 views
8

:Bir MediatR davranış boru hattına onaylama ekleyin? Ben <a href="http://github.com/jbogard/MediatR/wiki/Behaviors" rel="noreferrer">"behavior" pipelines</a> destekler ASP.NET Çekirdek, dahili kabı ve MediatR 3 kullanıyorum

public class MyRequest : IRequest<string> 
{ 
    // ... 
} 

public class MyRequestHandler : IRequestHandler<MyRequest, string> 
{ 
    public string Handle(MyRequest message) 
    { 
     return "Hello!"; 
    } 
} 

public class MyPipeline<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
{ 
    public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next) 
    { 
     var response = await next(); 
     return response; 
    } 
} 

// in `Startup.ConfigureServices()`: 
services.AddTransient(typeof(IPipelineBehavior<MyRequest,str‌​ing>), typeof(MyPipeline<MyRequest,string>)) 

Ben boru hattında FluentValidation doğrulayıcı gerekir. MediatR 2, bir validation pipeline was created thus:

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

    public ValidationPipeline(IRequestHandler<TRequest, TResponse> inner, IEnumerable<IValidator<TRequest>> validators) 
    { 
     _inner = inner; 
     _validators = validators; 
    } 

    public TResponse Handle(TRequest message) 
    { 
     var failures = _validators 
      .Select(v => v.Validate(message)) 
      .SelectMany(result => result.Errors) 
      .Where(f => f != null) 
      .ToList(); 
     if (failures.Any()) 
      throw new ValidationException(failures); 
     return _inner.Handle(request); 
    } 

} 

Nasıl yeni versiyonu için şimdi yapacağım? Hangi doğrulayıcıyı kullanacağımı nasıl belirlerim?

cevap

8

İşlem tam olarak aynı, sadece yeni IPipelineBehavior<TRequest, TResponse> arabirimini kullanmak için arabirimi değiştirmeniz gerekir. Onlar davranışlarında enjekte edilmeleri için

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
    where TRequest : IRequest<TResponse> 
{ 
    private readonly IEnumerable<IValidator<TRequest>> _validators; 

    public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators) 
    { 
     _validators = validators; 
    } 

    public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next) 
    { 
     var context = new ValidationContext(request); 
     var failures = _validators 
      .Select(v => v.Validate(context)) 
      .SelectMany(result => result.Errors) 
      .Where(f => f != null) 
      .ToList(); 

     if (failures.Count != 0) 
     { 
      throw new ValidationException(failures); 
     } 

     return next(); 
    } 
} 

doğrulayıcıları için, yerleşik kapta IValidator<TRequest> gibi tüm doğrulayıcılarını kayıt edilmelidir. Bunları tek tek kaydetmek istemiyorsanız, montaj tarama yeteneklerini getiren mükemmel Scrutor library modeline göz atmanızı öneririm. Bu şekilde validatorlarınızın kendisini bulacaksınız.

Ayrıca, yeni sistemle artık dekoratör kalıbı kullanmıyorsunuz, sadece genel davranışınızı kapsayıcınıza kaydediyorsunuz ve MediatR otomatik olarak alacaktır.

var services = new ServiceCollection(); 
services.AddMediatR(typeof(Program)); 
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); 
var provider = services.BuildServiceProvider(); 
+1

biri (Bunu diğer söz konusu anlamaya bana yardımcı oldu ben belirli türde bir kayıt biliyorum gerçi) Anlamadığım şey, neden bu tür şeyler için tüm örnekler açık kullanırım: Bu gibi bir şey olabilir kayıt için jenerikler? Elbette belirli bir dizi istek, işleyici vb. Için bir boru hattına ihtiyacınız var ve her talep için her boru hattına sahip değil misiniz? – grokky

+1

Sanırım buna bağlı. Örneğin, tüm isteklere doğrulama davranışının uygulanmasından memnunum. En kötü durum senaryosu, bu özel talep için onaylayıcılar kaydedilmemiştir ve bir sonraki davranışa veya fiili istek işleyicisine delege eden bir işsizlik haline gelir. Jenerik tutmak, kaydı da çok daha kolay hale getirir. Sorunu bildirdiğiniz için teşekkür ederim, bunu Autofac kullanan bir koddan aldım, ASP.NET Core'daki yerleşik kap dizileri desteklemiyor olabilir. –

+0

no-op validasyonu konusunda dikkatinizi çekerim. Ancak, açık jenerikler kullanılarak kaydedilen üç pipeliniz olduğunu varsayalım (belki de aptalca bir senaryo, hala bir MediatR acemi). Ve üçü de bir isteğin eşleştiğini varsayalım. Hepsi koşacak mı? – grokky

İlgili konular