通过attibute验证

时间:2017-11-17 07:12:12

标签: c# .net attributes

我想通过属性检查传递给方法的值是否正确,因为在方法体中添加if条件会使代码的可读性降低(在我看来)

例如,

    public object GetSomething(int id)
    {
        // there could be more conditions
        if (id<= 0)
            throw new ArgumentOutOfRangeException(nameof(id), $"Forbiden value: '{id}'");
        // real logic
        ...

我想检查一下

    [PossitiveValueAttr(id)]
    public object GetSomething(int id)
    {
        // real logic

或(我希望如此)

    public object GetSomething([PossitiveValueAttr] int id)
    {
        // real logic

1)你知道任何类似的现有灵魂吗?

2)如何将方法的参数传递给我的属性?

2 个答案:

答案 0 :(得分:1)

受曼弗雷德的启发......

因此,对于任何定义为

的方法
void DoSomething([Attr1] Type1 param1, [Attr2] Type2 param2, ...)
{
}

您很乐意添加该方法的第一个声明:

Validate(() => DoSomething(param1, param2, ...)) 

Attr1 / Attr2等都实现了ValidationAttribute:

[AttributeUsage(AttributeTargets.Parameter)]
public class ArgumentAttribute : Attribute
{
    public void Validate(string argumentName, object value)
    {
        // throw exception if not valid
    }
}

然后您可以将Validate实现为:

static void Validate(Expression<Action> expr)
{
    var body = (MethodCallExpression)expr.Body;

    foreach (MemberExpression a in body.Arguments)
    {
        FieldInfo fi = a.Member as FieldInfo;
        ParameterInfo pi = body.Method.GetParameters().FirstOrDefault(p => p.Name == fi.Name);
        ValidationAttribute va = pi?.GetCustomAttribute<ValidationAttribute>();
        if (va != null)
            va.Validate(pi.Name, fi.GetValue(((ConstantExpression)a.Expression).Value));
    }
}

并且通常在需要执行通过自定义属性定义的参数验证的任何地方使用它。

主要缺点是ValidationAttribute不是通用的,所以你总是得到一个普通的对象&#39;传递给你,你必须沮丧。

答案 1 :(得分:0)

除非您拥有查找并对其执行操作的代码,否则属性不会神奇地导致应用程序中的任何行为更改。 此外,只有在您拥有反射信息时才能确定属性,您无法获得函数参数。 但是对于你的特定例子(必须是正面的),为什么不使用unsigned int?