表达式`t => (t.SomeProperty As Object)`指的是方法,而不是属性

时间:2017-10-21 13:07:07

标签: c# linq lambda expression-trees

我在一些代码中创建了这个表达式:

t => (t.SomeProperty As Object)

现在我试图通过这个小片段获取属性名称(SomeProperty)(长时间从互联网上获取):

    public static PropertyInfo GetPropertyInfo<TSource, TProperty>
        (TSource source, Expression<Func<TSource, TProperty>> propertyLambda) {
        var type = typeof(TSource);

        var member = propertyLambda.Body as MemberExpression;
        if (member == null)
            throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property.");

        var propInfo = member.Member as PropertyInfo;
        if (propInfo == null)
            throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property.");

        if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType))
            throw new ArgumentException($"Expresion '{propertyLambda}' refers to a property that is not from type {type}.");

        return propInfo;
    }

但是如您所知,propertyLambda.Body as MemberExpression始终为空,因此:t => (t.Some1 As Object)不是属性引用。在这种情况下,有没有办法获得属性名称?

3 个答案:

答案 0 :(得分:4)

C#as运算符转换为Expression.TypeAs,C#转换运算符转换为Expression.ConvertExpression.ConvertChecked。如您所见,它们都是UnaryExpression类型,因此您可以使用Operand属性提取操作数表达式。你可以在一个循环中做到这一点,以支持多个演员阵容。

付诸行动,替换

var member = propertyLambda.Body as MemberExpression;

var operand = propertyLambda.Body;
while (operand.NodeType == ExpressionType.TypeAs || operand.NodeType == ExpressionType.Convert || operand.NodeType == ExpressionType.ConvertChecked)
    operand = ((UnaryExpression)operand).Operand;
var member = operand as MemberExpression;

答案 1 :(得分:1)

在您的情况下,您需要查看作为强制转换的一元表达式的操作数。

<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<input type="text"  title="Your name" id="name">
<button type="button" id="submit">Submit</button>

为了使程序更安全,您应该检查您的propertyLamba。 类似的东西:

((propertyLamdba.Body as UnaryExpression).Operand as MemberExpression).Member

答案 2 :(得分:0)

我建议这样做:

PropertyInfo info = t.GetType().GetProperty("SomeProperty",
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
// Use these binding flags to get a member of any visibility.

它为给定名称的属性返回PropertyInfo

如果您不想明确处理名称,请使用nameof(t.SomeProperty)

您可能还会发现方法.GetProperties对于获取特定类型的所有属性非常有用。