2012-09-14 30 views
30

he creado un method in C# para obtener methodnameNo se puede convertir objeto de tipo 'System.Linq.Expressions.UnaryExpression' al tipo 'System.Linq.Expressions.MemberExpression'

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

y decir que es 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 otros tipos da esta excepción:

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

  1. me cambió la cadena de oponerse en firma de método, pero luego vuelve a fallar.
  2. me cambió la llamada x => x.PropertyName-x => Convert.ToString(x.PropertyName) y todavía falla

¿Dónde estoy mal?

+2

IMO es mejor usar una variación de esto donde el ayudante toma una 'Expresión > '. Esto cambia la sintaxis del sitio de llamada a 'GetCorrectPropertyName ((= = this.Name)', que en mi opinión es mejor escribir (no es necesario dar el parámetro de tipo genérico) y mejor para leer ('this.Name' transmite el intento extremadamente bien). – Jon

+0

@Jon: Buddy no dude en agregar su respuesta. Si es mejor que la respuesta actual, definitivamente aceptaré la de usted. –

+0

No me gustaría hacer eso porque usurparía la intención de su pregunta. Pero puede obtener fácilmente el código desde [aquí] (http://compositewpf.codeplex.com/SourceControl/changeset/view/65392#1024364), Microsoft hace exactamente esto en Prism. – Jon

Respuesta

44

Necesita una línea separada para extraer el miembro donde la expresión de entrada es una expresión unaria.

acaba de convertir esto desde VB.Net, por lo que podría estar ligeramente desviado - quiero saber si tengo que hacer ningún ajuste de menor importancia:

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

Nota que la expresión de entrada no devuelve cadena necesariamente, que lo limita a solo leer propiedades que devuelven cadenas.

+4

Uno se pregunta por qué algo como esto aún no se ha incluido en el BCL o en una extensión. Es increíblemente útil. – BoltClock

+0

¿Solo quería saber cómo usarlo/llamarlo para obtener propiedades y métodos (sub y funciones de VB.Net)? –

+0

@NikhilAgrawal: es mejor que haga una nueva pregunta, haga referencia a esta y explique sus requisitos por completo. –

4

Después de hacer esta pregunta (sí, yo soy OP) he recibido comentarios sobre la Pregunta de Jon

y yo le ocurrió esta

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

Esto se apparently relacionado con el boxeo/unboxing. Las expresiones lambda que devuelven tipos de valores que requieren boxeo se representarán como UnaryExpressions, mientras que aquellas que devuelvan tipos de referencia se representarán como MemberExpressions.

Cuestiones relacionadas