2017-07-18 60 views
0

註冊IRequestPreProcessors我要註冊以下虛擬IRequestPreProcessor(中保3)無法與Mediatr

public class IdentifyUserTypeCommandHandler : IRequestPreProcessor<RegisterUserCommand> 
{ 
    private readonly IOptions<TecApiOptions> _options; 

    public IdentifyUserTypeCommandHandler(IOptions<TecApiOptions> options) 
    { 
     _options = options; 
    } 

    public async Task Process(RegisterUserCommand request) 
    { 
     request.Type = "internal"; 
     await Task.FromResult(true); 
    } 
} 

要做到這一點,我有我的容器安裝到IRequestPreProcessor映射到我的具體實施IdentifyUserTypeCommandHandler

 // Pipeline engine used internally to simplify controllers 
     services.AddMediatR(); 
     // Pre-processors 
     services.AddTransient(typeof(IRequestPreProcessor<RegisterUserCommand>), typeof(IdentifyUserTypeCommandHandler)); 

     // Registers command validator 
     services.AddTransient(typeof(IValidator<RegisterUserCommand>), typeof(RegisterUserCommandValidator)); 

     // Registers generic behaviors 
     services.AddTransient(typeof(IPipelineBehavior<,>), typeof(Pipeline<,>)); 
     services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>)); 
     services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>)); 
     services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>)); 

只要我運行代碼,我會得到以下異常

Sy stem.ArgumentException:打開通用服務類型'MediatR.Pipeline.IRequestPreProcessor ` 1 [TRequest]'需要註冊一個開放的通用實現類型。

我想只爲RegisterUserCommand類型的命令運行此預處理器。有關我如何解決這個問題的任何想法?

FYI的記錄,

public class LoggingBehavior<TCommand, TResponse> : IPipelineBehavior<TCommand, TResponse> 
{ 
    private readonly ILogger _logger; 

    public LoggingBehavior(ILoggerFactory loggerFactory) 
    { 
     _logger = loggerFactory?.CreateLogger(typeof(TCommand).Name) ?? throw new ArgumentNullException(nameof(loggerFactory)); 
    } 

    public async Task<TResponse> Handle(TCommand request, RequestHandlerDelegate<TResponse> next) 
    { 
     try 
     { 
      _logger.LogInformation(LoggingEvents.RUN_HANDLER, $"Handling '{typeof(TCommand).Name}'"); 
      var response = await next(); 
      _logger.LogInformation(LoggingEvents.RUN_HANDLER, $"Handled '{typeof(TResponse).Name}'"); 
      return response; 
     } 
     catch (Exception e) 
     { 
      _logger.LogError(
       LoggingEvents.RUN_HANDLER_EXCEPTION, e, 
       $"An error occured while processing pipeline '{GetType().Name}' [{typeof(TCommand).Name} >> {typeof(TResponse).Name}]"); 
      throw; 
     } 
    } 
} 

謝謝 問候, 勒布

+0

我假設'LoggingBehavior '和'ValidationBehavior '是裝飾者。您嘗試註冊的方式('IPipelineBehavior <,>')裝飾器,但通過堆疊它們將無法與.NET Core容器一起使用。 .NET Core不支持裝飾器。如果存在非通用註冊,則該註冊將首先進行,否則將選擇最後的註冊,但根據其自身而定,它將循環。 – Steven

+0

@Steven我已經檢查過,看來我的行爲按預期工作(至少當我調試我的應用程序時)。我主要是遵循這裏提到的東西>> https://github.com/jbogard/MediatR/wiki/Behaviors – Seb

+0

啊,我知道,管道行爲是_not_裝飾者。那麼我完全不同意這個:「這是一種更自然的方式來提高你的處理程序的行爲」,這是真的「在容器中更好地支持」,但這是國際海事組織對不做'正確的事情'的一個壞主張。 – Steven

回答

0

所以說話的lib的創造者之後,似乎前&後處理器必須有一個通用的定義。

public class GenericRequestPostProcessor<TRequest, TResponse> : IRequestPostProcessor<TRequest, TResponse> 

OR

public class GenericRequestPreProcessor<TRequest> : IRequestPreProcessor<TRequest> 

源:Examples

<TRequest><TRequest, TResponse>創建一個新的前置/後置處理器時是必需的。現在,1 000 000 $美元的問題,我稍後會嘗試回答:

如何我們專門處理器,以便他們處理一組特定的請求/命令(無需檢查請求類型)...

0

如果您使用services.AddMediatR()

確保您註冊內置的行爲:RequestPreProcessorBehavior

services.AddTransient(typeof(IPipelineBehavior<,>), typeof(RequestPreProcessorBehavior<,>)); 
services.AddMediatR(); 

然後您的預處理器需要有一般定義爲每@塞巴斯蒂安的回答是:

public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest> 
{ 
    public Task Process(TRequest request) 
    { 
     return Unit.Task; 
    } 
} 

如果你希望你的預處理器將只使用一個特定的請求:

public class PingDecorator<TRequest> : IRequestPreProcessor<TRequest> where TRequest:Ping 
{ 
    public Task Process(TRequest request) 
    { 
     request.Message = request.Message + " Decorated"; 
     return Unit.Task; 
    } 
}