作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个类有两个方法:
MaxLength(string text, int maxLength, string propName, string message = null);
MinValue(int value, int min, string propName, string message = null);
因为用户可以通过传入每个值来使用它。当他们想要验证一个类时,我想让它更容易,更像自动映射器。比如
public class MyModel {
public string Category { get; set; }
public int Number { get; set; }
}
此刻他们必须写
MyModel model = //comes from API call or where ever
var validator = new Validator();
validator.MaxLength(model.Category, 4, "Category");
validator.MinValue(model.Number , 3, "Number ");
我想要实现的是能够为类设置映射:
public class Profile1 : ClassValidationProfile
{
public Profile1()
{
CreateMap<Model1>()
.ForMember(x => x.Category, m => m.MaxLength(4))
.ForMember(x => x.Number , m => m.MinValue(3));
}
}
所以基于自动映射器我有:
IMappingExpression<T> ForMember<TMember>(Expression<Func<T, TMember>> member, Action<IValidatorExpression> memberAction)
但这将允许我设置 .ForMember(x => x.Name, m => m.MinValue(18))
这在运行时是不正确和错误的。
我希望能够将操作 memberAction
限制为它们的正确类型(字符串对字符串、整数对整数等)。因此,当用户设置他们的映射时,它知道哪些操作方法对于他们在表达式的第一部分中给出的属性类型是有效的。
然后它可以使用此信息为每个属性生成有效的验证器方法。
最佳答案
而不是 Action<IValidatorExpression>
, 你应该使用 TMember
的东西保留类型 - 例如Func<TMember, bool>
(一个函数,将成员值作为输入并返回一个 bool 值,指示验证是否通过)。
我尝试构建一个小示例程序,最终验证如下所示:
var validator = Validator<MyModel>.Create()
.ForMember(x => x.Category, cat => cat == "A")
.ForMember(x => x.Number, num => num < 200);
MyModel model = new MyModel {
Category = "A",
Number = 100,
};
validator.Validate(model);
这就是您要找的吗?
实现上述目的的代码如下:
class Validator<TClass> {
private List<IObjectValidator<TClass>> _constraints = new List<IObjectValidator<TClass>>();
public static Validator<TClass> Create() {
return new Validator<TClass>();
}
public Validator<TClass> ForMember<TMember>(Expression<Func<TClass, TMember>> memberSelectorExpression, Func<TMember, bool> memberValidation, string errorMessage = null) {
_constraints.Add(new ObjectValidator<TClass, TMember>(memberSelectorExpression.Compile(), memberValidation, errorMessage ?? memberSelectorExpression.ToString() + " did not pass validation"));
return this;
}
public void Validate(TClass obj) {
foreach (var constraint in _constraints) {
if (!constraint.Validate(obj))
throw new Exception(constraint.ErrorMessage);
}
}
}
interface IObjectValidator<T> {
bool Validate(T obj);
string ErrorMessage { get; }
}
class ObjectValidator<T, TMember> : IObjectValidator<T>
{
private Func<T, TMember> _memberSelector;
private Func<TMember, bool> _memberValidation;
public string ErrorMessage { get; }
public ObjectValidator(Func<T, TMember> memberSelector, Func<TMember, bool> memberValidation, string errorMessage) {
_memberSelector = memberSelector;
_memberValidation = memberValidation;
ErrorMessage = errorMessage;
}
public bool Validate(T obj)
{
return _memberValidation.Invoke(_memberSelector.Invoke(obj));
}
}
关于c# - Expression Func 和 action 如何将值形式的 func 传递给 action,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55683926/
我是一名优秀的程序员,十分优秀!