42

在 C# 中创建了一个方法来获取方法名

public string GetCorrectPropertyName<T>(Expression<Func<T, string>> expression)
{
   return ((MemberExpression)expression.Body).Member.Name; // Failure Point
}

并将其称为

string lcl_name = false;
public string Name
{
get { return lcl_name ; }
set 
    {
        lcl_name = value;
        OnPropertyChanged(GetCorrectPropertyName<ThisClassName>(x => x.Name));
}
}

如果属性是字符串并且所有其他类型都给出此异常,则此方法工作正常:

无法将“System.Linq.Expressions.UnaryExpression”类型的对象转换为“System.Linq.Expressions.MemberExpression”类型。

  1. 我在方法签名中将字符串更改为对象,但随后又失败了。
  2. 我将呼叫从更改x => x.PropertyNamex => Convert.ToString(x.PropertyName),但仍然失败

我哪里错了?

4

4 回答 4

69

您需要单独一行来提取输入表达式为一元表达式的成员。

刚刚从 VB.Net 转换了它,所以可能会稍微偏离 - 如果我需要做任何小的调整,请告诉我:

public string GetCorrectPropertyName<T>(Expression<Func<T, Object>> expression)
{
    if (expression.Body is MemberExpression) {
        return ((MemberExpression)expression.Body).Member.Name;
    }
    else {
        var op = ((UnaryExpression)expression.Body).Operand;
        return ((MemberExpression)op).Member.Name;
    }                
}

VB版本为:

Public Shared Function GetCorrectPropertyName(Of T) _
             (ByVal expression As Expression(Of Func(Of T, Object))) As String
    If TypeOf expression.Body Is MemberExpression Then
        Return DirectCast(expression.Body, MemberExpression).Member.Name
    Else
        Dim op = (CType(expression.Body, UnaryExpression).Operand)
        Return DirectCast(op, MemberExpression).Member.Name
    End If
End Function

请注意,输入表达式不一定返回字符串 - 这限制您只能读取返回字符串的属性。

于 2012-09-14T08:19:50.470 回答
13

显然与装箱/拆箱有关。返回需要装箱的值类型的 Lambda 表达式将表示为 UnaryExpressions,而返回引用类型的将表示为 MemberExpressions。

于 2014-11-28T07:58:57.583 回答
4

问完这个问题(是的,我是 OP)后,我收到了Jon对问题的评论

我想出了这个

public string ResolvePropertyName<TEntity>(Expression<Func<TEntity>> expression)
{
try {
    if (expression == null) {
        Throw New ArgumentNullException("propertyExpression")
    }

    object memberExpression = expression.Body as MemberExpression;
    if (memberExpression == null) {
        Throw New ArgumentException("The expression is not a member access expression.", "propertyExpression")
    }

    object property = memberExpression.Member as PropertyInfo;
    if (property == null) {
        Throw New ArgumentException("The member access expression does not access a property.", "propertyExpression")
    }

    object getMethod = property.GetGetMethod(true);
    if (getMethod.IsStatic) {
        Throw New ArgumentException("The referenced property is a static property.", "propertyExpression")
    }
    return memberExpression.Member.Name;
} catch (Exception ex) {
    return string.Empty;
}
}
于 2012-09-14T11:05:53.560 回答
1

上述答案的现代版本。

private static string GetPropertyName<T>(Expression<Func<T, object>> expression) 
=> expression.Body switch
{
    MemberExpression expr => expr.Member.Name,
    UnaryExpression expr => ((MemberExpression)expr.Operand).Member.Name,
    _ => throw new ArgumentException($"Argument {nameof(expression)} is not a property expression.", nameof(expression)),
};
于 2021-12-27T06:28:04.387 回答