无法将类型为“System.Linq.Expression.UnaryExpression”的对象强制转换为类型“System.Linq.Expression.MemberExpression”

wlsrxk51  于 2022-12-20  发布在  其他
关注(0)|答案(5)|浏览(588)

我创建了一个method in 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));
}
}

如果property是字符串,则此方法可以正常工作,而对于所有其他类型,则会出现以下异常:
无法将类型为“System.Linq.Expression.UnaryExpression”的对象强制转换为类型“System.Linq.Expression.MemberExpression”。
1.我在方法签名中将string更改为object,但它再次失败。
1.我将呼叫从x => x.PropertyName更改为x => Convert.ToString(x.PropertyName),但仍然失败
我哪里错了?

mdfafbf1

mdfafbf11#

如果输入表达式是一元表达式,则需要单独的一行来提取成员。
刚从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

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

li9yvcax

li9yvcax2#

这是与装箱/取消装箱相关的apparently。返回需要装箱的值类型的Lambda表达式将表示为UnaryExpressions,而返回引用类型的Lambda表达式将表示为MemberExpressions。

hm2xizp9

hm2xizp93#

问完这个问题(是的,我是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;
}
}
4c8rllxm

4c8rllxm4#

以上答案的现代版本。

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)),
};
iqih9akk

iqih9akk5#

如果您必须处理条件表达式,请添加以下内容:

else if (expression.Body is ConditionalExpression expr)
{
    return ((MemberExpression)((bool)(System.Linq.Expressions.Expression.Lambda(expr.Test).Compile().DynamicInvoke())
        ? expr.IfTrue
        : expr.IfFalse)).Member.Name;
}

相关问题