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

时间:2013-06-09 00:03:47

标签: c# asp.net .net asp.net-mvc fluentvalidation

我在 MVC4 项目中使用 FluentValidation 完美无缺,并且与 IoC StructureMap )相关联。

我有两个问题:

  1. 我应该如何管理验证器的生命周期?可以让他们单身吗?或者没有区别,我可以根据我的需要管理生命周期?这里的最佳做法是什么?

  2. FluentValidation 非常好。我一直在使用它来进行简单验证(例如:属性不为空等)。我正在考虑使用它进行一些 Db验证(例如:属性值是唯一的。)我可以使用<将存储库传递给它strong> StructureMap 并检查Db的值。 这是个好主意吗?或者我应该在服务层中而不是在我的IValidator中实现此逻辑?

  3. 如果您在类似场景中使用过它,那么您的体验是什么?

3 个答案:

答案 0 :(得分:5)

我已经使用了FluentValidation多年了,并且已经询问并找出了你的问题。

  1. 就个人而言,创建验证器的成本并不是很昂贵,所以我不会让它们成为单身人士。我遇到了需要访问HttpContext以要求文件上传的单身人士的问题。会发生的是第一个HttpContext总是在验证中使用而不是在当前验证中使用。
  2. 我个人建议你不要使用单身

    1. 我实际上一直这样做,我喜欢它。请注意,您注入的任何依赖都应该是有效的。如果您的数据库查询执行全表扫描并需要30秒,那么这不是一个好的体验。就像我上面说的那样,我通常会注入HttpContext来检查文件是否上传,并且我传递了一个DataContext来验证电子邮件是否尚未被采用。
    2. 对此疯狂,这是FluentValidation的一大优势,只需确保依赖性在时间和资源方面并不昂贵。

答案 1 :(得分:4)

我刚刚使用Unity和MVC 4来调查此事。

我所看到的是,如果你将它们保留为瞬态物体。 FluentValidation将为每个已验证的属性创建新的验证对象。所以需要一些缓存。

对于我的缓存,我已经查看了验证器的Per Request缓存。这适用于所有依赖组件是按请求。 (Per Request是自定义代码,它在HttpContext.Current.Items集合中存储子Unity容器,其中HTTP模块在请求结束时销毁/丢弃子容器)

要在验证器的Per Request和Singleton时刻之间进行选择,可以归结为如何使用它以及它具有哪种类型的依赖关系以及IoC Continer的能力。

使用unity可以创建单例验证器并使用函数(即Func serviceFunc)注入服务工厂。

在我的情况下,每次调用serviceFunc时,都会检索Unity ChildContiner“服务”。因此,我仍然可以使用ContainerControlledLifetimeManager(singleton)定义我的'validator',并使用HierarchicalLifetimeManager(Per Request)定义'service'。

这样做的缺点是每次调用serviceFunc时都需要检查并从子容器中检索服务。这将是我回到'每个请求'的最可能原因)

我刚刚更新了我的代码以使用serviceFunc,并将在今天进行测试。我相信为您的申请找到正确的解决方案将是一次错误的尝试。

下面是我正在使用的验证工厂 - 而不是使用统一容器(如网上的大多数示例),我正在将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;
        }
    }
}

答案 2 :(得分:2)

验证不足为奇,通常取决于您的应用程序的架构,但这是我的想法。

  1. 验证员应根据您的需要进行管理。我通常会将静态类实例留给典型的服务基础设施问题,如工厂或对象构建器。

  2. 毫无疑问,FluentValidation库非常棒。验证面临的典型问题不是您选择的库的结果,而是应用验证的方式。在大多数典型的应用程序中,对象/实体/域的验证是上下文的,因此验证完全取决于您尝试执行的操作的上下文。例如,对于持久性,更改属性,更改状态,ETL等,对同一对象的验证可能不同。记住所有这些我相信验证属于尽可能接近正在执行的操作。

  3. 希望这有帮助。