9

.NET 框架中是否有办法将某个方法或验证器传递给其类用Data Annotations修饰的对象实例,并接收错误集合?

我看到在 .NET 4.x 中有一种方法可以做到这一点。但是.NET 3.5 中是否有类似的机制?

4

3 回答 3

12

稍加思考,您就可以构建自己的验证器来扫描ValidationAttributes您拥有的属性。它可能不是一个完美的解决方案,但如果您仅限于使用 .NET 3.5,这似乎是一个轻量级的解决方案,希望您能理解。

static void Main(string[] args)
{

    Person p = new Person();
    p.Age = 4;

    var results = Validator.Validate(p);

    results.ToList().ForEach(error => Console.WriteLine(error));

    Console.Read();
}       

// Simple Validator class
public static class Validator
{
    // This could return a ValidationResult object etc
    public static IEnumerable<string> Validate(object o)
    {
        Type type = o.GetType();
        PropertyInfo[] properties = type.GetProperties();
        Type attrType = typeof (ValidationAttribute);

        foreach (var propertyInfo in properties)
        {
            object[] customAttributes = propertyInfo.GetCustomAttributes(attrType, inherit: true);

            foreach (var customAttribute in customAttributes)
            {
                var validationAttribute = (ValidationAttribute)customAttribute;

                bool isValid = validationAttribute.IsValid(propertyInfo.GetValue(o, BindingFlags.GetProperty, null, null, null));

                if (!isValid)
                {
                    yield return validationAttribute.ErrorMessage;
                }
            }
        }
    }
}

public class Person
{
    [Required(ErrorMessage = "Name is required!")]
    public string Name { get; set; }

    [Range(5, 20, ErrorMessage = "Must be between 5 and 20!")]
    public int Age { get; set; }
}

这会将以下内容打印到控制台:

姓名是必填项!
必须在 5 到 20 之间!

于 2013-06-24T22:55:34.340 回答
7

Linq 版本

public static class Validator
{
    public static IEnumerable<string> Validate(object o)
        {
            return TypeDescriptor
                .GetProperties(o.GetType())
                .Cast<PropertyDescriptor>()
                .SelectMany(pd => pd.Attributes.OfType<ValidationAttribute>()
                                    .Where(va => !va.IsValid(pd.GetValue(o))))
                                    .Select(xx => xx.ErrorMessage);
        }
    }
于 2014-12-17T14:33:53.780 回答
0

这些数据注释的东西主要在另一个框架的上下文中工作,例如。带有 Razor、Fluent 等的 MVC。如果没有其他框架,注释就是这样,它们是标记代码,并且需要框架/额外代码来进行解释。

注解本身并不是真正的 AOP/Intercept,因此注解在用注解修饰的对象提交给知道如何解释/解析标记代码(通常通过反射)的中间框架之前什么都不做。

对于可以使注释本质上工作的真正 AoP,您将需要 PostSharp/Unity 等。这些框架在运行/编译时修改 IL 并重新路由原始代码。

于 2013-06-24T23:08:53.170 回答