问题描述
我正在使用.NET Core中的FluentValidator。大部分情况下,一切工作都很好,但是我注意到当使用复杂类型时,FluentValidator会显示完整的属性名称。例如,假设我有一个名为Address的类,具有Street,City,State和Zip属性。现在,假设我有一个由名为Physical Address的模型属性支持的表单。如果我需要街道,Fluent将显示以下验证错误:
'Physical Address. Street' must not be empty.
我更喜欢这样,只是说“街道”一定不能为空,因为我可能在页面上有多个地址字段,因此仅显示“街道”还不够具体。但我宁愿说:
'Physical Address Street' must not be empty.
(单词地址后没有句点)
FluentValidation给出的用于全局覆盖显示名称的示例是在Startup.cs中添加该名称:
ValidatorOptions.displayNameResolver = (type,member,expression) => {
if(member != null) {
return member.Name + "Foo";
}
return null;
};
覆盖示例有效,但使用此示例(减去foo部分)将显示此验证错误:
'Street' must not be empty.
(我不想要的是因为它太通用了)
我需要知道的是,lambda内部的哪种逻辑会产生与默认行为(即 Physical Address。Street ,而不仅仅是 Street )完全相同的结果。知道了这一点之后,我就可以用简单的defaultValue.Replace(".","")
来消除句点。谢谢!
解决方法
更新:
更简单的方法是使用ValidatorOptions.Global.PropertyNameResolver
ValidatorOptions.Global.DisplayNameResolver = (type,memberInfo,expression) =>
ValidatorOptions.Global.PropertyNameResolver(type,expression).SplitPascalCase();
原始答案:
准备了完整的演示注意:我使用的是ValidatorOptions.Global.DisplayNameResolver
而不是ValidatorOptions.DisplayNameResolver
,因为它已过时,并将在以后的版本中删除
using FluentValidation;
using FluentValidation.Internal;
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace ConsoleApp4
{
public class Root
{
public PhysicalAddress PhysicalAddress { get; set; }
= new PhysicalAddress();
}
public class PhysicalAddress
{
public string Street { get; set; }
}
public class RootValidator : AbstractValidator<Root>
{
public RootValidator()
{
RuleFor(x => x.PhysicalAddress.Street).NotNull();
}
}
class Program
{
static string DefaultPropertyNameResolver(Type type,MemberInfo memberInfo,LambdaExpression expression)
{
if (expression != null)
{
var chain = PropertyChain.FromExpression(expression);
if (chain.Count > 0) return chain.ToString();
}
return memberInfo?.Name;
}
static void Main(string[] args)
{
ValidatorOptions.Global.DisplayNameResolver = (type,expression) =>
DefaultPropertyNameResolver(type,expression).SplitPascalCase();
var res = new RootValidator().Validate(new Root());
}
}
}