简体   繁体   English

FluentValidation,Validators生命周期以及使用Validators检查Db

[英]FluentValidation, Validators lifecycle and using Validators to check against Db

I'm using FluentValidation in my MVC4 project. 我在我的MVC4项目中使用FluentValidation Every thing works perfectly and it's connected to my IoC ( StructureMap ). 每件事都很完美 ,它与我的IoCStructureMap )相连。

I have 2 questions: 我有两个问题:

  1. How should I manage lifecycle of my validators ? 我该如何管理验证器的生命周期 Is it ok to make them singleton ? 可以让他们成为单身人士吗? or it makes no difference and I can manage lifecycle according to my needs ? 或者没有区别,我可以根据自己的需要管理生命周期 What is the best practice here? 这里的最佳做法是什么?

  2. FluentValidation is very good. FluentValidation非常好。 I have been using it for simple validations (like: property is not empty, etc.). 我一直在使用它进行简单的验证 (例如:属性不是空的等)。 I'm thinking about doing some Db validations using it(like: property value is unique .) I can pass my repository to it using StructureMap and check values against Db. 我正在考虑使用它做一些Db验证 (比如: 属性值是唯一的 。)我可以使用StructureMap将我的存储库传递给它,并检查Db的值。 Is this a good idea ? 这是个好主意吗? or should I implement this logic in my service layer and not in my IValidator? 或者我应该在我的服务层而不是在我的IValidator中实现这个逻辑?

If you used it in similar scenarios, what was your experience? 如果您在类似场景中使用它,您的体验是什么?

I've used FluentValidation for years now and have asked and figured out your questions. 我已经使用了FluentValidation多年了,并且已经问过并找出了你的问题。

  1. Personally the cost of creating a validator is not very expensive, so I do not make them singletons. 就个人而言,创建验证器的成本并不是很昂贵,所以我不会让它们成为单身人士。 I've run into issues with Singletons that required access to the HttpContext to require a file upload. 我遇到了需要访问HttpContext以要求文件上传的单身人士的问题。 What happens is the first HttpContext is always used in the validation rather than the current one. 会发生的是第一个HttpContext总是在验证中使用而不是在当前验证中使用。

I personally recommend you DON'T use singletons . 我个人建议你不要使用单身人士

  1. I actually do this all the time and I like it. 我实际上一直这样做,我喜欢它。 Just be mindful that any dependency you inject should be efficient. 请注意,您注入的任何依赖都应该是有效的。 If your database query does a full table scan and takes 30 seconds, then that isn't a good experience. 如果您的数据库查询执行全表扫描并需要30秒,那么这不是一个好的体验。 Like I said above, I usually inject HttpContext to check if files were uploaded, and I pass a DataContext to validate an email isn't already taken. 就像我上面说的那样,我通常会注入HttpContext来检查文件是否上传,并且我传递了一个DataContext来验证电子邮件是否尚未被采用。

Go crazy with this, it is a huge advantage of FluentValidation, just make sure the dependency isn't expensive in regards to time and resources. 对此疯狂,它是FluentValidation的一个巨大优势,只需确保依赖性在时间和资源方面并不昂贵。

I have just been looking into this myself using unity and MVC 4. 我刚刚使用unity和MVC 4来调查这个问题。

What I have seen is that if you keep them as Transient objects. 我所看到的是,如果你将它们保留为瞬态对象。 FluentValidation will create a new validation object for every property that is been validated. FluentValidation将为每个已验证的属性创建新的验证对象。 So some caching is required. 所以需要一些缓存。

For my caching I have looked at Per Request caching of the validator. 对于我的缓存,我已经查看了验证器的Per Request缓存。 This works well as all the dependent components are Per Request. 这适用于所有依赖组件是按请求。 (Per Request is custom code which stores a child Unity Container on the HttpContext.Current.Items collections with a HTTP module that destroys/dispose the Child Container at the end of the request) (Per Request是自定义代码,它在HttpContext.Current.Items集合中存储子Unity容器,其中HTTP模块在请求结束时销毁/丢弃子容器)

To choose between Per Request and Singleton instants of the validator comes down to how your using it and what type of dependencies it has and the capablities of the IoC Continer. 要在验证器的Per Request和Singleton时刻之间进行选择,可以归结为如何使用它以及它具有哪种类型的依赖关系以及IoC Continer的功能。

With unity you can create a singleton validator and inject the service factory using a function ie Func serviceFunc. 使用unity,您可以创建单例验证器并使用函数(即Func serviceFunc)注入服务工厂。

In my case each time I call the serviceFunc, the Unity ChildContiner 'service' is retrieved. 在我的情况下,每次调用serviceFunc时,都会检索Unity ChildContiner“服务”。 Thus I can still have my 'validator' defined with a ContainerControlledLifetimeManager(singleton) and have the 'service' defined with HierarchicalLifetimeManager(Per Request). 因此,我仍然可以使用ContainerControlledLifetimeManager(singleton)定义我的'validator',并使用HierarchicalLifetimeManager(Per Request)定义'service'。

A downside of this is each time the serviceFunc is invoked it needs to check and retrieves the service from the child container. 这样做的缺点是每次调用serviceFunc时都需要检查并从子容器中检索服务。 This will be the most likely reason why I will do back to 'per request') 这将是我回到'每个请求'的最可能原因)

I have just updated my code to use serviceFunc and will test it today. 我刚刚更新了我的代码以使用serviceFunc,并将在今天进行测试。 I believe it will be trial an error to find the correct solution for your aplications. 我相信为您的申请找到正确的解决方案将是一次错误的试验。

Below is the validtion factory I'm using - instead of using the unity container (as most examples on the web do), I'm injecting the IDependencyResolver into it and using that to resolve my validator objects. 下面是我正在使用的验证工厂 - 而不是使用统一容器(如Web上的大多数示例所示),我正在将IDependencyResolver注入其中并使用它来解析我的验证器对象。

public class ValidatorFactory : IValidatorFactory 
{
    private readonly IDependencyResolver _dependencyResolver;

    // taken from the attribute Validation factory
    public ValidatorFactory(IDependencyResolver dependencyResolver)
    {
        _dependencyResolver = dependencyResolver;
    }

    /// <summary>
    /// Gets a validator for the appropriate type.
    /// 
    /// </summary>
    public IValidator<T> GetValidator<T>()
    {
        return (IValidator<T>)this.GetValidator(typeof(T));
    }

    /// <summary>
    /// Gets a validator for the appropriate type.
    /// 
    /// </summary>
    public virtual IValidator GetValidator(Type type)
    {
        if (type == (Type)null)
            return (IValidator)null;
        var validatorAttribute = (ValidatorAttribute)Attribute.GetCustomAttribute((MemberInfo)type, typeof(ValidatorAttribute));
        if (validatorAttribute == null || validatorAttribute.ValidatorType == (Type) null)
        {
            return (IValidator) null;
        }
        else
        {
            return _dependencyResolver.GetService(validatorAttribute.ValidatorType) as IValidator;
        }
    }
}

Validation is unsurprisingly a complex and usually depends on the architecture for your application, but here are my thoughts. 验证是一个复杂的,并且通常取决于您的应用程序的架构,但这是我的想法。

  1. Validators should be managed according to your needs. 验证员应根据您的需要进行管理。 I would typically leave static class instances to typically serving infrastructure concerns like factories or object builders. 我通常会将静态类实例留给典型的服务基础设施问题,如工厂或对象构建器。

  2. Without doubt the FluentValidation library is great. 毫无疑问,FluentValidation库非常棒。 Typical problems faced by validation are not a result of the library you choose but the way in which validation is applied. 验证面临的典型问题不是您选择的库的结果,而是应用验证的方式。 In most typical application validation of an object / entity / domain is contextual, whereby validation depends completely on the context of the operation you're trying to perform. 在大多数典型的应用程序中,对象/实体/域的验证是上下文的,因此验证完全取决于您尝试执行的操作的上下文。 For example validation on the same object is likely to be different for persistence, changing an attribute, changing state, for ETL, etc. Keeping all of this in mind I believe that validation belongs as close to the operation being performed as possible. 例如,对于持久性,更改属性,更改状态,ETL等,对同一对象的验证可能不同。记住所有这些我相信验证属于尽可能接近正在执行的操作。

Hopefully this helps. 希望这会有所帮助。

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

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