web-dev-qa-db-ja.com

タイプ「System.Linq.Expressions.UnaryExpression」のオブジェクトをタイプ「System.Linq.Expressions.MemberExpression」にキャストできません

メソッド名を取得するために 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.PropertyName_からx => Convert.ToString(x.PropertyName)に変更しましたが、それでも失敗します

どこが間違っているのですか?

35
Nikhil Agrawal

入力式が単項式であるメンバーを抽出するには、別の行が必要です。

これを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

入力式は必ずしも文字列を返すわけではないことに注意してください。これにより、文字列を返すプロパティの読み取りのみに制限されます。

57
Jon Egerton

これは どうやら ボクシング/アンボクシングに関連しています。ボクシングを必要とする値の型を返すラムダ式はUnaryExpressionsとして表されますが、参照型を返す式はMemberExpressionsとして表されます。

9
Scott Munro

この質問をした後(はい、私は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;
}
}
4
Nikhil Agrawal