Impossible de convertir l'objet de type 'System.Linq.Expressions.UnaryExpression' en type 'System.Linq.Expressions.MemberExpression'

c# exception-handling expression-trees linq

Question

J'ai créé une méthode en C # pour obtenir methodname

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

et l'appelant comme

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

Cela fonctionne bien si la propriété est string et que pour tous les autres types, cette exception est donnée:

Impossible de convertir l'objet de type 'System.Linq.Expressions.UnaryExpression' en type 'System.Linq.Expressions.MemberExpression'.

  1. J'ai changé de chaîne en objet dans la signature de la méthode, mais cela a de nouveau échoué.
  2. J'ai changé l'appel de x => x.PropertyName en x => Convert.ToString(x.PropertyName) et il échoue toujours

Où est-ce que je me trompe?

Réponse acceptée

Vous avez besoin d'une ligne séparée pour extraire le membre où l'expression d'entrée est une expression unaire.

Je viens de convertir cela à partir de VB.Net, donc ça pourrait être un peu en retrait - dites-moi si j'ai besoin de faire des ajustements mineurs:

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;
    }                
}

La version VB est:

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

Notez que l'expression d'entrée ne renvoie pas nécessairement de chaîne, ce qui vous oblige à lire uniquement les propriétés renvoyant des chaînes.


Réponse populaire

Ceci est apparemment lié à la boxe / unboxing. Les expressions Lambda renvoyant des types de valeur nécessitant une boxe seront représentées par UnaryExpressions, tandis que celles renvoyant des types de référence seront représentées par MemberExpressions.



Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow
Sous licence: CC-BY-SA with attribution
Non affilié à Stack Overflow