在 Fluent 验证之前转换 属性
Transform property before Fluent Validation
我需要先转换我的 属性(删除字符串上的白色 space),然后再应用验证。
具体来说,我想检查一个字符串是否是枚举的一部分,但该字符串可能包含白色spaces(据我所知枚举不允许)
类似...
RuleFor(x => x.Value).IsEnumName(typeof(EnumType))
(x.Value 应该先去掉白色space)
您可以使用自定义方法
RuleFor(x => x.Valor).Must(BeEnumType);
...
private bool BeEnumType(string v)
{
return Enum.IsDefined(typeof(EnumType), v.Replace(" ", string.Empty));
}
FluentValidation 方法Transform
就是为这种情况设计的。以下使用 Everson 回答中的基本白色 space 去除剂:
RuleFor(x => x.Value)
.Transform(x => x.Replace(" ", string.Empty))
.IsEnumName(typeof(EnumType));
我会选择使用更强效的白色 space 去除剂来去除标签等
RuleFor(x => x.Value)
.Transform(x => new string(x.Where(c => !Char.IsWhiteSpace(c)).ToArray()))
.IsEnumName(typeof(EnumType));
不需要自定义验证器(例如,Must
),我个人会避免编写一个,除非别无他法。
我会把那个白色的 space 移除器放到一个扩展中(MVP,你应该处理 null 的情况;我的偏好是 null guard 但那是另一个话题):
public static class StringExtensions
{
public static string RemoveWhiteSpace(this string target){
return new string(target.Where(c => !Char.IsWhiteSpace(c)).ToArray());
}
}
那么规则的可读性就高了很多:
RuleFor(x => x.Value)
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType))
.When(x => x != null);
需要注意的事项:我发现如果 Transform
返回 null
,则 IsEnumName
规则将通过。我个人不喜欢这样,所以我会包含一个 When
规则构建器选项,以仅在提供 Value
时进行测试,或者包含一个非空规则以确保提供它。
工作 LINQPad 示例:
public enum EnumType
{
Value1,
Value2,
Value3
}
public class Foo
{
public Guid Id { get; set; }
public string Value { get; set; }
}
public class FooValidator : AbstractValidator<Foo>
{
public FooValidator()
{
RuleFor(x => x.Value)
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType));
.When(x => x != null);
}
}
public static class StringExtensions
{
public static string RemoveWhiteSpace(this string target)
{
return new string(target.Where(c => !Char.IsWhiteSpace(c)).ToArray());
}
}
void Main()
{
var validator = new FooValidator();
var foo1 = new Foo { Id = Guid.NewGuid(), Value = "Value 1" };
var result1 = validator.Validate(foo1);
Console.WriteLine(result1.IsValid);
var foo2 = new Foo { Id = Guid.NewGuid(), Value = "Value2" };
var result2 = validator.Validate(foo2);
Console.WriteLine(result2.IsValid);
var foo3 = new Foo { Id = Guid.NewGuid(), Value = "Value 3" };
var result3 = validator.Validate(foo3);
Console.WriteLine(result3.IsValid);
var foo4 = new Foo { Id = Guid.NewGuid(), Value = "This is not a valid enum value" };
var result4 = validator.Validate(foo4);
Console.WriteLine(result4.IsValid);
var foo5 = new Foo { Id = Guid.NewGuid(), Value = null };
var result5 = validator.Validate(foo5);
Console.WriteLine(result5.IsValid);
}
编辑:
根据您关于将所有这些包装到扩展中的附加评论:
public static class FluentValidationExtensions
{
public static IRuleBuilderOptions<T, string> IsEnumTypeMember<T>(this IRuleBuilderInitial<T, string> target)
{
return target
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType))
.When(x => x != null);
}
}
然后更新规则以使用它:
RuleFor(x => x.Value).IsEnumTypeMember();
这只是一个 MVP,我并不真正了解您的所有用例;你可能想让它更通用,这样你就可以将它应用于其他枚举。
我需要先转换我的 属性(删除字符串上的白色 space),然后再应用验证。
具体来说,我想检查一个字符串是否是枚举的一部分,但该字符串可能包含白色spaces(据我所知枚举不允许)
类似...
RuleFor(x => x.Value).IsEnumName(typeof(EnumType))
(x.Value 应该先去掉白色space)
您可以使用自定义方法
RuleFor(x => x.Valor).Must(BeEnumType);
...
private bool BeEnumType(string v)
{
return Enum.IsDefined(typeof(EnumType), v.Replace(" ", string.Empty));
}
FluentValidation 方法Transform
就是为这种情况设计的。以下使用 Everson 回答中的基本白色 space 去除剂:
RuleFor(x => x.Value)
.Transform(x => x.Replace(" ", string.Empty))
.IsEnumName(typeof(EnumType));
我会选择使用更强效的白色 space 去除剂来去除标签等
RuleFor(x => x.Value)
.Transform(x => new string(x.Where(c => !Char.IsWhiteSpace(c)).ToArray()))
.IsEnumName(typeof(EnumType));
不需要自定义验证器(例如,Must
),我个人会避免编写一个,除非别无他法。
我会把那个白色的 space 移除器放到一个扩展中(MVP,你应该处理 null 的情况;我的偏好是 null guard 但那是另一个话题):
public static class StringExtensions
{
public static string RemoveWhiteSpace(this string target){
return new string(target.Where(c => !Char.IsWhiteSpace(c)).ToArray());
}
}
那么规则的可读性就高了很多:
RuleFor(x => x.Value)
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType))
.When(x => x != null);
需要注意的事项:我发现如果 Transform
返回 null
,则 IsEnumName
规则将通过。我个人不喜欢这样,所以我会包含一个 When
规则构建器选项,以仅在提供 Value
时进行测试,或者包含一个非空规则以确保提供它。
工作 LINQPad 示例:
public enum EnumType
{
Value1,
Value2,
Value3
}
public class Foo
{
public Guid Id { get; set; }
public string Value { get; set; }
}
public class FooValidator : AbstractValidator<Foo>
{
public FooValidator()
{
RuleFor(x => x.Value)
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType));
.When(x => x != null);
}
}
public static class StringExtensions
{
public static string RemoveWhiteSpace(this string target)
{
return new string(target.Where(c => !Char.IsWhiteSpace(c)).ToArray());
}
}
void Main()
{
var validator = new FooValidator();
var foo1 = new Foo { Id = Guid.NewGuid(), Value = "Value 1" };
var result1 = validator.Validate(foo1);
Console.WriteLine(result1.IsValid);
var foo2 = new Foo { Id = Guid.NewGuid(), Value = "Value2" };
var result2 = validator.Validate(foo2);
Console.WriteLine(result2.IsValid);
var foo3 = new Foo { Id = Guid.NewGuid(), Value = "Value 3" };
var result3 = validator.Validate(foo3);
Console.WriteLine(result3.IsValid);
var foo4 = new Foo { Id = Guid.NewGuid(), Value = "This is not a valid enum value" };
var result4 = validator.Validate(foo4);
Console.WriteLine(result4.IsValid);
var foo5 = new Foo { Id = Guid.NewGuid(), Value = null };
var result5 = validator.Validate(foo5);
Console.WriteLine(result5.IsValid);
}
编辑:
根据您关于将所有这些包装到扩展中的附加评论:
public static class FluentValidationExtensions
{
public static IRuleBuilderOptions<T, string> IsEnumTypeMember<T>(this IRuleBuilderInitial<T, string> target)
{
return target
.Transform(x => x?.RemoveWhiteSpace())
.IsEnumName(typeof(EnumType))
.When(x => x != null);
}
}
然后更新规则以使用它:
RuleFor(x => x.Value).IsEnumTypeMember();
这只是一个 MVP,我并不真正了解您的所有用例;你可能想让它更通用,这样你就可以将它应用于其他枚举。