【问题标题】:Can't replace string propertyName parameter with lambda expression无法用 lambda 表达式替换字符串 propertyName 参数
【发布时间】:2016-01-31 08:17:44
【问题描述】:

我使用以下代码从 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;

我收到此错误:

无法将表达式类型“int”转换为返回类型“RangeAttribute”

我该如何解决这个问题?

【问题讨论】:

    标签: c# lambda data-annotations


    【解决方案1】:

    您同时使用泛型类型 T 作为 attributeproperty 的类型。尝试从:

    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&lt;RangeAttribute, int&gt;(() =&gt; Id).Maximum;

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

    【讨论】:

    • 是的,我最终意识到了这一点。它只能在类本身工作。 this.Id 在这种情况下可能很有用。很好的解决方案。
    猜你喜欢
    • 2011-04-12
    • 2016-11-09
    • 2011-01-07
    • 2012-04-26
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多