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.PropertyNameましたがx => 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

これは明らかにボクシング/アンボクシングに関連しています。ボックス化が必要な値型を返すラムダ式はUnaryExpressionsとして表されますが、参照型を返すラムダ式はMemberExpressionsとして表されます。

于 2014-11-28T07:58:57.583 に答える
4

この質問をした後(はい、私はOPです)、ジョンから質問に対するコメントを受け取りました

そして私はこれを思いついた

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 に答える