Impossible de lancer objet du système de type'.Linq.Expression.UnaryExpression' de type 'System.Linq.Expression.MemberExpression"

j'ai créé une méthode dans C# pour obtenir le nom de la méthode

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

et l'appelant

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

cela fonctionne très bien si la propriété est chaîne et pour tous les autres types donne cette exception:

impossible de lancer objet du système de type.Linq.Expression.UnaryExpression' de type 'System.Linq.Expression.MemberExpression".

  1. I changé de chaîne pour objet de signature de la méthode, mais alors il échoue à nouveau.
  2. j'ai changé l'appel de x => x.PropertyName à x => Convert.ToString(x.PropertyName) et il échoue toujours

Où ai-je tort?

32
demandé sur Community 2012-09-14 12:09:06

3 réponses

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

vient de convertir CE de VB.Net, donc pourrait être légèrement off-me faire savoir si j'ai besoin de faire des modifications mineures:

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 input ne renvoie pas nécessairement string - ce qui vous contraint à ne lire que les propriétés qui renvoient des chaînes.

48
répondu Jon Egerton 2014-11-17 16:11:35

c'est apparemment lié à la boxe/unboxing. Les expressions Lambda retournant des types de valeur qui nécessitent de la boxe seront représentées comme des expressions simples tandis que celles qui renvoient des types de référence seront représentées comme des expressions MemberExpressions.

5
répondu Scott Munro 2014-11-28 07:58:57

après avoir posé cette question(oui je suis OP) j'ai reçu des commentaires sur la question de Jon

et j'ai trouvé ce

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
répondu Nikhil Agrawal 2017-05-23 12:26:05