无法用lambda表达式替换字符串propertyName参数

时间:2016-01-31 08:17:45

标签: c# lambda data-annotations

我使用以下代码从DataAnnotations获取属性:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute
{
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(propertyName);
    return (T)property .GetCustomAttributes(attrType, false).First();
}

感谢用户:jgauffin

我希望通过传递lambda表达式而不是字符串来改进他的解决方案:

public static T GetAttributeFrom<T>(this object instance, Expression<Func<T>> propertyExpression) where T : Attribute
{
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(GetPropertyNameFromLambdaExpression(propertyExpression));
    return (T)property.GetCustomAttributes(attrType, false).First();
}

和我从这个表达式中获取不动产名称的方法:

public static string GetPropertyNameFromLambdaExpression<T>(Expression<Func<T>> propertyAsExpression)
{
    var memberExpression = propertyAsExpression.Body as MemberExpression;
    var propertyInfo = memberExpression.Member as PropertyInfo;
    if (memberExpression != null && propertyInfo != null)
    {
        return memberExpression.Member.Name;
    }
    throw new ArgumentException(propertyAsExpression.ToString());
}

如果我尝试这样的话:

var id = this.GetAttributeFrom<RangeAttribute>(()=> Id).Maximum;

我收到此错误:

  

无法转换表达式类型&#39; int&#39;返回类型&#39; RangeAttribute&#39;

我该如何解决这个问题?

1 个答案:

答案 0 :(得分:4)

您正在使用泛型类型T作为属性的类型和属性。试着开始:

public static T GetAttributeFrom<T>(this object instance, string propertyName) where T : Attribute {
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(propertyName);
    return (T)property.GetCustomAttributes(attrType, false).First();
}

public static T GetAttributeFrom<T, U>(this object instance, Expression<Func<U>> propertyExpression) where T : Attribute {
    var attrType = typeof(T);
    var property = instance.GetType().GetProperty(GetPropertyNameFromLambdaExpression<U>(propertyExpression));
    return (T)property.GetCustomAttributes(attrType, false).First();
}

public static string GetPropertyNameFromLambdaExpression<U>(Expression<Func<U>> propertyAsExpression) {
    var memberExpression = propertyAsExpression.Body as MemberExpression;
    var propertyInfo = memberExpression.Member as PropertyInfo;
    if (memberExpression != null && propertyInfo != null) {
        return memberExpression.Member.Name;
    }
    throw new ArgumentException(propertyAsExpression.ToString());
}

然后你可以用这种方式调用它:

var max = this.GetAttributeFrom<RangeAttribute, int>(() => Id).Maximum;

您不能省略第二种类型(GetAttributeFrom<RangeAttribute>(() => Id)):C# generics can't infer second parameter?