gpt4 book ai didi

c# - 使用 Fluent 验证的 Model T 的通用验证器?

转载 作者:行者123 更新时间:2023-11-30 23:04:53 24 4
gpt4 key购买 nike

我昨天刚接触 Fluent Validation,我觉得它很酷。我已经尝试过了并且有效。但是我的应用程序目前有多个模型,我必须承认为每个模型编写验证器压力很大。是否可以用泛型编写并找到一种方法来验证每个模型?

我的验证器目前就是这样写的。但是我不知道如何用泛型来写它。

EmployeeValidator.cs

public class EmployeeValidator : AbstractValidator<EmployeeViewModel>
{
private readonly ValidationEntitySettingServices _validationEntitySettingService;

public EmployeeValidator(ValidationEntitySettingServices validationEntitySettingService)
{
_validationEntitySettingService = validationEntitySettingService;

RuleFor(x => x.LastName).NotEmpty().When(x => IsPropertyRequired(x.LastName)).WithMessage("Last Name is a required field!");
RuleFor(x => x.FirstName).NotEmpty().When(x => IsPropertyRequired(x.FirstName)).WithMessage("First Name is a required field!");
RuleFor(x => x.MiddleName).NotEmpty().When(x => IsPropertyRequired(x.MiddleName)).WithMessage("Middle Name is a required field!");
}

public bool IsPropertyRequired(string propertyName)
{
var empValidationSetting = _validationEntitySettingService.GetIncluding("Employee");
if (empValidationSetting != null)
{
return empValidationSetting.ValidationEntityProperties.Any(p => p.PropertyName.Equals(propertyName) && p.IsRequired);
}
else
return false;
}
}

提前致谢。

最佳答案

我认为使验证通用化没有任何意义,因为您的所有模型都可能具有需要以不同方式验证的不同属性和属性类型。但是,您可以通过添加基本验证类来使此处的内容更通用,例如:

public abstract class BaseValidator<T> : AbstractValidator<T>
{
private readonly ValidationEntitySettingServices _validationEntitySettingService;

public BaseValidator(ValidationEntitySettingServices validationEntitySettingService)
{
_validationEntitySettingService = validationEntitySettingService;
AutoApplyEmptyRules();
}

private string ViewModelName
{
get { return GetType().Name.Replace("Validator", string.Empty); }
}

// no longer needed
//public bool IsPropertyRequired(string propertyName)
//{
// var validationSetting = _validationEntitySettingService.GetIncluding(ViewModelName);
// if (validationSetting != null)
// {
// return validationSetting.ValidationEntityProperties.Any(p => p.PropertyName.Equals(propertyName) && p.IsRequired);
// }
// else
// return false;
//}

protected void AddEmptyRuleFor<TProperty>(Expression<Func<T, TProperty>> expression, string message)
{
//RuleFor(expression).NotEmpty().When(x => IsPropertyRequired(((MemberExpression)expression.Body).Name)).WithMessage(message);
RuleFor(expression).NotEmpty().WithMessage(message);
}

private void AddEmptyRuleForProperty(PropertyInfo property)
{
MethodInfo methodInfo = GetType().GetMethod("AddEmptyRuleFor");
Type[] argumentTypes = new Type[] { typeof(T), property.PropertyType };
MethodInfo genericMethod = methodInfo.MakeGenericMethod(argumentTypes);
object propertyExpression = ExpressionHelper.CreateMemberExpressionForProperty<T>(property);
genericMethod.Invoke(this, new object[] { propertyExpression, $"{propertyInfo.Name} is a required field!" });
}

private PropertyInfo[] GetRequiredProperties()
{
var validationSetting = _validationEntitySettingService.GetIncluding(ViewModelName);
if (validationSetting != null)
{
return validationSetting.ValidationEntityProperties.Where(p => p.IsRequired);
}
else
return null;
}

private void AutoApplyEmptyRules()
{
PropertyInfo[] properties = GetRequiredProperties();
if (properties == null)
return;
foreach (PropertyInfo propertyInfo in properties)
{
AddEmptyRuleForProperty(property);
}
}
}

此处的主要要求是 AddEmptyRuleForProperty 方法,它将通过基于 PropertyType 构造方法来调用通用 AddEmptyRuleFor 方法。

然后您可以改为继承此类并使用泛型方法应用规则:

public class EmployeeValidator : BaseValidator<EmployeeViewModel>
{
public EmployeeValidator(ValidationEntitySettingServices validationEntitySettingService) : base(validationEntitySettingService)
{
// no longer needed
//AddEmptyRuleFor(x => x.LastName, "Last Name is a required field!");
//AddEmptyRuleFor(x => x.FirstName, "First Name is a required field!");
//AddEmptyRuleFor(x => x.MiddleName, "Middle Name is a required field!");
}
}

这是 ExpressionHelper 类,它提供了一种创建通用成员表达式作为对象的方法,该对象可以在调用上面的 AddEmptyRuleFor 方法时传入:

public static class ExpressionHelper
{
public static Expression<Func<TModel, TProperty>> CreateMemberExpression<TModel, TProperty>(PropertyInfo propertyInfo)
{
if (propertyInfo == null)
throw new ArgumentException("Argument cannot be null", "propertyInfo");

ParameterExpression entityParam = Expression.Parameter(typeof(TModel), "x");
Expression columnExpr = Expression.Property(entityParam, propertyInfo);

if (propertyInfo.PropertyType != typeof(T))
columnExpr = Expression.Convert(columnExpr, typeof(T));

return Expression.Lambda<Func<TModel, TProperty>>(columnExpr, entityParam);
}

public static object CreateMemberExpressionForProperty<TModel>(PropertyInfo property)
{
MethodInfo methodInfo = typeof(ExpressionHelper).GetMethod("CreateMemberExpression", BindingFlags.Static | BindingFlags.Public);
Type[] argumentTypes = new Type[] { typeof(TModel), property.PropertyType };
MethodInfo genericMethod = methodInfo.MakeGenericMethod(argumentTypes);
return genericMethod.Invoke(null, new object[] { property });
}
}

关于c# - 使用 Fluent 验证的 Model T 的通用验证器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49108649/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com