No se puede convertir el objeto de tipo 'System.Linq.Expressions.UnaryExpression' para escribir 'System.Linq.Expressions.MemberExpression'

c# exception-handling expression-trees linq

Pregunta

Creé un método en C # para obtener el nombre del método

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

y llamándolo como

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

Esto funciona bien si la propiedad es una cadena y para todos los demás tipos da esta excepción:

No se puede convertir el objeto de tipo 'System.Linq.Expressions.UnaryExpression' para escribir 'System.Linq.Expressions.MemberExpression'.

  1. Cambié la cadena a objeto en la firma del método, pero luego vuelve a fallar.
  2. Cambié la llamada de x => x.PropertyName a x => Convert.ToString(x.PropertyName) y todavía falla

Donde me equivoco

Respuesta aceptada

Necesita una línea separada para extraer el Miembro donde la expresión de entrada es una Expresión Unaria.

Acabo de convertir esto de VB.Net, así que podría estar un poco deshabilitado. Avísame si necesito hacer algunos ajustes menores:

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 versión de VB es:

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

Tenga en cuenta que la expresión de entrada no devuelve necesariamente una cadena, lo que le obliga a leer solo las propiedades que devuelven cadenas.


Respuesta popular

Al parecer, esto está relacionado con el boxeo / unboxing. Las expresiones Lambda que devuelven tipos de valor que requieren boxeo se representarán como UnaryExpressions, mientras que las que devuelven tipos de referencia se representarán como MemberExpressions.



Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow
Licencia bajo: CC-BY-SA with attribution
No afiliado con Stack Overflow