MediatR 行为的约束违反异常

Mig*_*ura 6 c# mediatr asp.net-core

我将MediatR与以下类一起使用:

public class GetPostsRequest : IRequest<Envelope<GetPostsResponse>> {
  public Int32 Age { get; set; }
}

public class GetPostResponse {
  public String Title { get; set; }
  public String Content { get; set; }      
}
Run Code Online (Sandbox Code Playgroud)

其中 Envelope 是一个包装类:

public class Envelope<T> {
  public List<T> Result { get; private set; } = new List<T>();  
  public List<Error> Errors { get; private set; } = new List<Error>();
}
Run Code Online (Sandbox Code Playgroud)

由中介发送的 GetPostsRequest 由 Handler 执行:

public class GetPostsRequestHandler : IRequestHandler<GetPostsRequest, Envelope<GetPostsResponse>> {

  public async Task<Envelope<GetPostsResponse>> Handle(GetPostsRequest request, CancellationToken cancellationToken) {
  }

}
Run Code Online (Sandbox Code Playgroud)

MediatR 允许使用在特定请求的处理程序之前执行的行为。我创建了一个ValidationBehavior如下:

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, Envelope<TResponse>> 
    where TRequest : IRequest<Envelope<TResponse>> {

  private readonly IEnumerable<IValidator<TRequest>> _validators;

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

  public Task<Envelope<TResponse>> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<Envelope<TResponse>> next) {

    ValidationContext context = new ValidationContext(request);

    List<Error> errors = _validators
      .Select(x => x.Validate(context))
      .SelectMany(x => x.Errors)
      .Select(x => new Error(ErrorCode.DataNotValid, x.ErrorMessage, x.PropertyName))
      .ToList();

    if (errors.Any())
      return Task.FromResult<Envelope<TResponse>>(new Envelope<TResponse>(errors));  

    return next();

  }

}
Run Code Online (Sandbox Code Playgroud)

我在 ASP.NET Core 应用程序上注册了 ValidationBehavior:

services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
Run Code Online (Sandbox Code Playgroud)

当我调用 API 时,出现以下错误:

An unhandled exception has occurred while executing the request.
System.ArgumentException: GenericArguments[0], 'TRequest', on 'ValidationBehavior`2[TRequest,TResponse]' violates the constraint of type 'TRequest'. 
---> System.TypeLoadException: GenericArguments[0], 'TRequest', on 'ValidationBehavior`2[TRequest,TResponse]' violates the constraint of type parameter 'TRequest'.
Run Code Online (Sandbox Code Playgroud)

我错过了什么?

pok*_*oke 2

services.AddScoped(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不\xe2\x80\x99t 认为这条线做了你期望它做的事情。

\n\n

在您的示例中,您的请求类型是 a IRequest<Envelope<Response>>,因此当 MediatR 查找管道行为时,它将查找IPipelineBehavior<Request, Envelope<Response>>.

\n\n

由于 DI 容器中有一个开放式通用注册IPipelineBehavior<,>,因此将使用该实现。因此,来自的泛型类型参数IPipelineBehavior<,>将用于实例化 的类型ValidationBehavior<,>

\n\n

所以对于IPipelineBehavior<Request, Envelope<Response>>,这将创建一个ValidationBehavior<Request, Envelope<Response>>. 这意味着在您的通用实现中,TRequestwill beRequestTResponsewill be Envelope<Response>。然而,这意味着您的类型的类型约束意味着TRequest,或者Request在本例中,需要实现IRequest<Envelope<Envelope<Response>>>. 当然,情况并非如此,因此这解释了您所看到的类型约束违规。

\n\n

不幸的是,这意味着您无法按照您希望的方式进行操作。您不能对泛型类型施加类型约束,至少不能对Envelope<T>.

\n