【问题标题】:Is there a way to make FluentValidation more dynamic?有没有办法让 FluentValidation 更有活力?
【发布时间】:2019-02-08 13:50:04
【问题描述】:

我们刚刚从供应商那里收到了第 1 阶段的版本,用 Angular 5 将一个古老的 PowerBuilder 应用程序转换为 C# MVC(我们有一个 Angular 人,他已经在 7 中大部分重写了前端,所以来自 5 的安全问题不是问题)。由于工作说明书只要求他们重现应用程序,因此对输入的验证几乎为零,因为原始应用程序上没有太多(如果有的话)。

我最近对 ​​FluentValidation 进行了一些研究,并喜欢它在以后将使用相同整体数据的应用程序中的可重用性。然而,看看这段代码,MVC 中的模型并没有像它们应该的那样被规范化,所以我们有几十个模型可能会被规范化,这样数据字段中的重叠就会减少,例如名字、姓氏、地址、公司地址等

我在泛型和反射方面有基本经验,并且过去支持过一些更高级的示例。所以我试图找到一些方法来利用这两个概念来使验证器更具动态性。

除了与给定命名模型的基本硬连接之外,我找不到更多更高级的 FluentValidation 示例。我尝试使用通用 T 代替模型,但无法弥合差距并访问传递给验证的对象。

 public class FormValidator : AbstractValidator<ModelExample>
 {
     public FormValidation()
     {

     }
 }   

//tried to do something like this but wasn't able to access the .HasProperties. Although I was able to access the GetProperties, 
//having trouble implementing it into the RuleFor however.
 public class FormValidation<T> : AbstractValidator<T>
{
    RuleFor(x => x.GetType().GetProperty(nameof({something if it exists}).{check stuff is valid}
{

public class ModelExample
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
}

public class OtherModelExample
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

我的最终目标是能够将相关对象传递给给定的验证器,它能够确定属性是否存在并采取相应的行动。

这可能是一个我真的不知道如何在 Google 中提出问题的问题,我倾向于以某种方式表达我所期望的问题。

这甚至可能也不可能,但如果它可以让我免于编写一系列硬耦合验证器,如果我们被允许规范化数据流,我可能需要在以后重写这些验证器,那将有很大帮助。

任何比我发现的简单示例更高级的文章或文档,即使在这个项目之外,也会很有用。我发现的大多数教程都是非常基本的示例,有时我很难在“真实”代码应用程序中描绘它们。

谢谢

【问题讨论】:

  • 你有什么突破吗?我也被困住了。我尝试过使用各种技巧和技巧(即 ExpandoObject、类索引器...等)。但没有运气。
  • @AlvinfromDiaspar 我还没有实现它,并且在工作中与另一个项目分道扬镳,但我确实得到了相当于一个帮助器/包装器的东西,你传入了你需要验证的类型和名称它会为你处理的。我原计划在证明它按照我在脑海中看到的方式工作后立即发布它,但到目前为止,截止日期已经受到阻碍。这可能不是一个理想的解决方案,但在每个控制器中节省了一些编码。
  • @Stagmoth - 我找到了一个可行的通用解决方案。我在这里解释了我的步骤。 stackoverflow.com/questions/57151623/…

标签: c# generics reflection fluentvalidation


【解决方案1】:

您是否考虑过相反的情况并为每个属性创建它们,而不是为整个模型创建通用验证器?

如果您使用custom property validators,您可以指定验证器逻辑一次,然后只需为每个视图模型创建一个验证器类。

例如:

class Program
{
    static void Main(string[] args)
    {
        var person = new Person
        {
            Name = "Ada",
            NickName = "A"
        };
        var validator = new PersonValidator();
        var result = validator.Validate(person);

        //Should be a problem with the NickName
    }
}
class Person
{
    public string Name { get; set; }
    public string NickName { get; set; }
}

class PersonValidator : AbstractValidator<Person>
{
    public PersonValidator()
    {
        RuleFor(x => x.Name).SetValidator(new NameValidator());
        RuleFor(x => x.NickName).SetValidator(new NameValidator());
    }
}

public class NameValidator : AbstractValidator<string>
{
    public NameValidator()
    {
        RuleFor(x => x).Must(x => x.Length > 1)
            .WithMessage("The name is not long enough");
    }
}

这可能也是一个更安全的选择,因为它是选择加入而不是隐含的。

【讨论】:

  • 难道这还不需要我为每个模型制作一个验证器吗?还是实例化大量类来验证所有这些字段?也许我无法将这些点与我最初的问题联系起来。
  • 是的,但是可以使用组合,例如:如果人有一个地址,而不是拥有一个包含所有地址属性的平面视图模型,则将地址包裹在一个单独的班级。还有另一种涉及可能工作的接口的替代方案(例如:通过每个类的接口指定属性),但 iirc 它需要一个自定义验证器工厂并且实现起来相当复杂..它也几乎肯定不会开箱即用任何客户端验证。
  • 谢谢,我想我可以使用 AutoFac 对所有 AbstractValidator 对象使用反射从整个文件夹中压缩一些进行构建的实例化。我会对此进行调查以减轻整个过程中的显式调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-13
  • 2017-03-26
  • 2011-11-02
  • 1970-01-01
  • 2013-05-26
  • 2020-06-25
  • 1970-01-01
相关资源
最近更新 更多