Validating DataAnnotations on method parameters

百般思念 提交于 2020-04-07 07:09:06

问题


How are data annotation attributes to be used with method parameters? I'm expecting to do something like this, but an exception isn't thrown.

private string TestValidate([StringLength(5)] string name = "Default: throw exception")
{
    ValidationContext context = new ValidationContext(name);
    Validator.ValidateObject(name, context);
    return name;
}

Alternatively, I know this will work. However, this doesn't use the convenience of the attribute convention.

private string TestValidate(string name = "Default: throw exception")
{
    ValidationContext context = new ValidationContext(name);
    Validator.ValidateValue(name, context, new[] { new StringLengthAttribute(5) });
        return name;
}

回答1:


If you are wanting to instrument your code, then you'd use a bit of reflection (see https://msdn.microsoft.com/en-us/library/system.reflection.parameterinfo.attributes(v=vs.110).aspx)

You can evaluate your reflection once on class initialization, but this is how the reflection code would work:

// NOTE: nameof() is a .NET 4.6 feature.  If you are using an older
// version of .NET, you'll have to write the string yourself.
MethodInfo method = GetType().GetMethod(nameof(TestValidate), typeof(string));
// NOTE: it's on you to validate this and use the version with binding flags for
// special cases like non-public and static methods

ParameterInfo parameter = method.GetParameters().First();
// This is shorthand: GetCustomAttributes returns object[], you'll have
// convert that properly and reference your customAttributes later
ValidationAttribute[] customAttributes = parameter.GetCustomAttributes(
        typeof(ValidationAttribute), true); // second parameter ignored

// At this point you can handle the rest of your validation
ValidationContext context = new ValidationContext(name);
Validator.ValidateValue(name, context, customAttributes);
    return name;

Many validation frameworks simply encapsulate all the reflection necessary to get at the validation attributes. NOTE: in this case I used the subclass of ValidationAttribute as opposed to the more specific StringLengthAttribute. The call to GetCustomAttributes() will return any attribute that extends the base class we asked for. That allows you to completely change the attributes you have on your method and add more constraints without changing the code at all. You'll have to make some changes if you evaluate more than one parameter or remove a parameter.

You could make this a bit more generic as the code from the time you have a specific MethodInfo object would be generally the same. I'd probably make a couple changes in that case:

public static void Validate(MethodInfo method, params object[] values)
{
    ValidationContext context = new ValidationContext(method.Name);
    ParameterInfo[] parameters = method.GetParameters();

    for(int i = 0; i < Math.Min(parameters.Length, values.Length); i++)
    {
        // This is shorthand: GetCustomAttributes returns object[], you'll have
        // convert that properly and reference your customAttributes later
        ValidationAttribute[] customAttributes = parameter[i].GetCustomAttributes(
                typeof(ValidationAttribute), true); // second parameter ignored

        Validator.ValidateValue(values[i], context, customAttributes);
    }
}


来源:https://stackoverflow.com/questions/35343137/validating-dataannotations-on-method-parameters

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!