C# 在WinC窗体应用程序中对自定义属性使用FluentValidation

C# 在WinC窗体应用程序中对自定义属性使用FluentValidation,c#,.net,winforms,fluentvalidation,C#,.net,Winforms,Fluentvalidation,我目前正在开发一个链接到数据库的应用程序,但它不使用EntityFramework来生成数据库对象。相反,我创建了处理实体的自定义类。这些实体中的字段也使用自定义类。下面是一个简单的例子: 公共类BookEntity:实体 { 公共字段BookId{get;set;} 公共字段名{get;set;} 公共字段页{get;set;} 公共簿记实体 { BookId=新的外业手簿\u BookId; 名称=新的野外作业手册\u名称; 第页=新的野外作业手册第页; } } 公共类字段 { 公共字符串视

我目前正在开发一个链接到数据库的应用程序,但它不使用EntityFramework来生成数据库对象。相反,我创建了处理实体的自定义类。这些实体中的字段也使用自定义类。下面是一个简单的例子:

公共类BookEntity:实体 { 公共字段BookId{get;set;} 公共字段名{get;set;} 公共字段页{get;set;} 公共簿记实体 { BookId=新的外业手簿\u BookId; 名称=新的野外作业手册\u名称; 第页=新的野外作业手册第页; } } 公共类字段 { 公共字符串视域{get;set;} 公共对象值{get;set;} } 如您所见,我的Field类包含两个属性。第一个包含带有Tablename的字段名,另一个是值

我的问题是,使用FluentValidation,我希望能够将返回的属性名称设置为我的Viewfield属性。我目前可以使用WithState扩展来实现这一点,但是我需要在每个fluent验证规则中指定它

私有类BookValidator:AbstractValidator { /// ///包含所有验证规则的构造函数 /// 公共图书验证器 { RuleForp=>Double?p.Page.Value .NotNull.WithStatep=>p.Page.Viewfield .LessThanOrEqualTop=>1000.WithStatep=>p.Page.Viewfield .GreaterThanOrEqualTop=>100.WithStatep=>p.Page.Viewfield } } 我确实尝试过使用PropertyNameResolver,但由于在resolver中无法访问Book的实例,因此无法访问Viewfield属性

我想要的是能够避免与国家重复的东西

另外,请注意,我不能在字段上使用自定义属性来设置视口

我希望我解释得很好


谢谢。

我不知道FluentValidation,但我认为您的实现实在太奇怪了,无法得到支持,也许FluentValidation有某种可插入的机制来获取您可以钩住的属性值,但我怀疑。。。不管怎么说,奇怪对于奇怪的顺便说一句,这真的很奇怪:D,您可以将所有FluentAPI封装到您自己的扩展中,比如NotNullEx、LessThanOrEqualToEx等

这些扩展只需在对应的FluentAPI上多取一个参数,然后在扩展中调用FluentValidation验证器并返回其结果,这样就可以链接并保持语法流畅

e、 g

可能成为

RuleFor(p => (Double?)p.Page.Value)
        .NotNullEx(p => p.Page.Viewfield)
这对您没有多大帮助,因为如果您让扩展接受字符串来选择属性名,您无论如何都需要指定linq选择器或STRAINT参数值

另一种方法是创建您自己的验证器,从原始验证器继承并将其挂接到FluentValidator,无论哪种方法,您都应该传递该属性值,因此我认为这无论如何都不是完美的解决方案

更新: 阅读这里的WithState扩展,在我看来,您可以在RuleFor之后调用WithState。。。并不是每一条验证线都是如此

所以不是

RuleFor(p => (Double?)p.Page.Value)
   .NotNull().WithState(p => p.Page.Viewfield)
   .LessThanOrEqualTo(p => 1000).WithState(p => p.Page.Viewfield)
   .GreaterThanOrEqualTo(p =>100).WithState(p => p.Page.Viewfield)
你可以试试看

RuleFor(p => (Double?)p.Page.Value)
   .NotNull()
   .WithState(p => p.Page.Viewfield)
   .LessThanOrEqualTo(p => 1000)
   .GreaterThanOrEqualTo(p =>100)

这行得通吗?

这似乎是一种不使用ORM的过于复杂的方式……为什么不使用public int BookId{get;set;}?其他属性也是一样。我希望能够做到这一点,甚至可以将框架迁移到EntityFramework,但我目前无法做到。正如@DavidG所说,这是一种不使用ORM的过于复杂的方法,但我现在必须使用它……这仍然不能解释为什么会有这个奇怪的字段类?这个字段类包含的信息比我在示例中输入的要多得多。由于框架目前正在运行,我没有时间,现在不想破坏任何东西。我知道这看起来很奇怪,但我必须要解决这个问题。现在,我确实复制了.WithState函数,但我只想知道是否有人能更容易地使用FluentValidation和我现有的类模式来实现这一点。是的,我认为我当前的框架不适合支持FluentValidation框架。我确实尝试过进行扩展,但我必须重写FluentValidation的整个验证过程,以保留我的自定义值,直到返回ValidationResult。虽然它可以工作,但它比在每个验证规则步骤上复制.WithState行要复杂得多。谢谢你的帮助您敢肯定需要为单个字段上的每种验证指定WithState吗?在我看来,在这里阅读WithState扩展时,您可以在RuleFor之后调用它……我无法在RuleFor之后调用它,因为WithState是IRuleBuilderOptions的扩展,而RuleFor返回IRuleBuilderInitial时,我尝试使用IRuleBuilderInitial创建自己的WithState扩展,它确实起了作用。但是,在设置配置时
但是,它给了我一个错误,因为配置还没有创建,而且只是在第一次验证之后?可能这是一个不需要的功能,但可以工作,因为它在内部调用规则。配置,我认为这保持设置始终相同的propertyname,可能值得一试,请参阅更新的答案我也尝试过。因为第二次验证覆盖了第一次验证,所以它不起作用。例如,使用更新的代码,如果我的值为null,则我的状态将为p.Page.Viewfield,这很好,但是如果我的值为23,则状态将为null。
RuleFor(p => (Double?)p.Page.Value)
   .NotNull()
   .WithState(p => p.Page.Viewfield)
   .LessThanOrEqualTo(p => 1000)
   .GreaterThanOrEqualTo(p =>100)