简体   繁体   English

FluentValidation验证器和简单注入器,其中验证器作为数组注入

[英]FluentValidation Validators and Simple Injector where Validators Injected as Array

I'm having a few problems getting my FluentValidation validators working with Simple Injector. 我在使用Simple Injector时使用FluentValidation验证器时遇到了一些问题。

I have a decorator with a constructor of: 我有一个装饰器,其构造函数为:

public CommandHandlerValidationDecorator(
    IRequestHandler<TRequest, TRepsonse> innerHandler, 
    IValidator<TRequest>[] validators)
{
    _decoratedHandler = innerHandler;
    _validators = validators;
}

The issue is with the 2nd parameter, IValidator<TRequest>[] validators . 问题在于第二个参数IValidator<TRequest>[] validators

Guided by the error messages I was getting, I did my configuration as follows: 在我收到的错误消息的指导下,我按照以下方式进行了配置:

container.Register(typeof(FluentValidation.IValidator<>), new[] { assembly });
container.RegisterCollection(typeof(FluentValidation.IValidator<>), new[] { assembly });
container.Register(typeof(IRequestHandler<,>),new [] { assembly });
container.RegisterDecorator(typeof(IRequestHandler<,>), 
    typeof(CommandHandlerValidationDecorator<,>));

This worked fine, up until I changed the lifetime scoping to per web request: 这工作正常,直到我将生命周期范围更改为每个Web请求:

container.Register(typeof(FluentValidation.IValidator<>), new[] { assembly }, 
    Lifestyle.Scoped);
container.RegisterCollection(typeof(FluentValidation.IValidator<>), new[] { assembly });
container.Register(typeof(IRequestHandler<,>),new [] { assembly }, Lifestyle.Scoped);
container.RegisterDecorator(typeof(IRequestHandler<,>), 
    typeof(CommandHandlerValidationDecorator<,>), Lifestyle.Scoped);

It looks as though you cannot scope RegisterCollection to per web request and that becomes a problem because an exception is thrown owing to a lifestyle mismatch: 看起来好像你不能将RegisterCollection的范围扩展到每个web请求,这会成为一个问题,因为生活方式不匹配会引发异常:

Additional information: A lifestyle mismatch is encountered. 附加信息:遇到生活方式不匹配。 CommandHandlerValidationDecorator (Web Request) depends on IValidator[] (Transient). CommandHandlerValidationDecorator(Web请求)依赖于IValidator [](瞬态)。 Lifestyle mismatches can cause concurrency bugs in your application. 生活方式不匹配会导致应用程序出现并发错误。 Please see https://simpleinjector.org/dialm to understand this problem and how to solve it. 请参阅https://simpleinjector.org/dialm以了解此问题以及如何解决此问题。

Perhaps I am trying to force something which is bad practice? 也许我试图强迫一些不好的做法?

What you're seeing is described here in the documentation: 什么你描述看到这里的文件中:

Simple Injector preserves the lifestyle of instances that are returned from an injected IEnumerable<T> , ICollection<T> , IList<T> , IReadOnlyCollection<T> and IReadOnlyList<T> instances. Simple Injector保留从注入的IEnumerable<T>ICollection<T>IList<T>IReadOnlyCollection<T>IReadOnlyList<T>实例返回的实例的生活方式。 In reality you should not see the the injected IEnumerable<T> as a collection of instances; 实际上,您不应该将注入的IEnumerable<T>视为实例集合; you should consider it a stream of instances. 你应该把它看作一个实例流。 Simple Injector will always inject a reference to the same stream (the IEnumerable<T> or ICollection<T> itself is a singleton) and each time you iterate the IEnumerable<T> , for each individual component, the container is asked to resolve the instance based on the lifestyle of that component. Simple Injector将始终注入对同一个流的引用( IEnumerable<T>ICollection<T>本身是一个单例),每次迭代IEnumerable<T> ,对于每个单独的组件,要求容器解析基于该组件的生活方式的实例。

Warning : In contrast to the collection abstractions, an array is registered as transient. 警告 :与集合抽象相反,数组被注册为瞬态。 An array is a mutable type; 数组是可变类型; a consumer can change the contents of an array. 消费者可以更改数组的内容。 Sharing the array (by making it singleton) might cause unrelated parts of your applications to fail because of changes to the array. 共享数组(通过使其成为单例)可能会导致应用程序的不相关部分因阵列更改而失败。 Since an array is a concrete type, it can not function as a stream, causing the elements in the array to get the lifetime of the consuming component. 由于数组是具体类型,因此它不能用作流,从而导致数组中的元素获取消耗组件的生命周期。 This could cause lifestyle mismatches when the array wasn't registered as transient. 当阵列未注册为瞬态时,这可能会导致生活方式不匹配

So you've got two options: 所以你有两个选择:

  1. Make the consumers of the array transient as well, or 使阵列的消费者也是瞬态的,或者
  2. Change the parameter's argument from array to IEnumerable<T> , ICollection<T> , IList<T> , IReadOnlyCollection<T> or IReadOnlyList<T> . 将参数的参数从数组更改为IEnumerable<T>ICollection<T>IList<T>IReadOnlyCollection<T>IReadOnlyList<T>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM