[英]How can I use the Data Validation Attributes in C# in a non-ASP.net context?
I'd like to use the data validation attributes in a library assembly, so that any consumer of the data can validate it without using a ModelBinder (in a console application, for instance). 我想在库程序集中使用数据验证属性,这样数据的任何使用者都可以在不使用ModelBinder的情况下对其进行验证(例如,在控制台应用程序中)。 How can I do it? 我该怎么做?
Actually this is pretty cool. 其实这很酷。 I used it in a WFP validation implementation recently. 我最近在WFP验证实施中使用它。 Most people end up writing lots of code using reflection to iterate the attributes, but there's a built in function for this. 大多数人最终使用反射来编写大量代码来迭代属性,但是有一个内置函数。
var vc = new ValidationContext(myObject, null, null);
return Validator.TryValidateObject(myObject, vc, null, true);
You can also validate attributes on a single named property. 您还可以在单个命名属性上验证属性。 You can also optionally pass in a list in order to access the error messages : 您还可以选择传入列表以访问错误消息:
var results = new List<ValidationResult>();
var vc = new ValidationContext(myObject, null, null) { MemberName = "UserName"};
var isValid = Validator.TryValidateProperty(value, vc, results);
// get all the errors
var errors = Array.ConvertAll(results.ToArray(), o => o.ErrorMessage);
The System.ComponentModel.DataAnnotations.ValidationAttribute
classes have IsValid
methods that perform the validation logic. System.ComponentModel.DataAnnotations.ValidationAttribute
类具有执行验证逻辑的IsValid
方法。 They take an Object (the value of the field they decorate) and return true
or false
. 它们获取一个Object(它们装饰的字段的值)并返回true
或false
。
You can use these attributes, and a little reflection, to roll your own aspect-oriented validator. 您可以使用这些属性和一些反射来推动您自己的面向方面的验证器。 Pass your validator an object, and the validator will get a list of PropertyInfo
s and FieldInfo
s. 将验证器传递给对象,验证器将获得PropertyInfo
和FieldInfo
的列表。 For each of these, it can call GetCustomAttributes
to look for those that inherit from ValidationAttribute
, and for each of these, call IsValid
, passing the value of the property or field. 对于其中的每一个,它可以调用GetCustomAttributes
来查找从ValidationAttribute
继承的那些,并为每个调用IsValid
,传递属性或字段的值。 This can be done totally dynamically without knowing the structure of the class to be validated at design-time. 这可以完全动态地完成,而不需要知道要在设计时验证的类的结构。
TryValidateProperty
is just badly written - you have to jump through hoops to get it to work outside a Controller, and even then, if you use it twice, it will end up quietly setting ModelState to valid/invalid and stop alterring that state, and stop returning accurate results from then on. TryValidateProperty
编写得很糟糕 - 你必须通过箍来让它在Controller之外工作,即使这样,如果你使用它两次,它最终会安静地将ModelState设置为有效/无效并停止改变该状态,并停止从那时起返回准确的结果。
I gave up on it and just wrote my own validator. 我放弃了它,只是写了我自己的验证器。 This'll loop over any set of objects in any context and tell you if they're valid: 这将循环遍历任何上下文中的任何对象集,并告诉您它们是否有效:
bool isValid = true;
var invalidFields = new List<string>();
foreach (var o in viewModels)
{
var properties = o.GetType()
.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach(var prop in properties)
{
var attrs = prop.GetCustomAttributes(true);
if (attrs != null)
{
var val = prop.GetValue(o);
ValidationAttribute[] validatorAttrs = attrs
.Where(a => a is ValidationAttribute)
.Select(a => (ValidationAttribute)a).ToArray();
foreach(var attr in validatorAttrs)
{
bool thisFieldIsValid = attr.IsValid(val);
if (!thisFieldIsValid)
invalidFields.Add(prop.Name);
isValid = isValid && thisFieldIsValid;
}
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.