2012-09-14 15 views
30

ho creato un method in C# per ottenere methodnameImpossibile eseguire il cast oggetto di tipo 'System.Linq.Expressions.UnaryExpression' digitare 'System.Linq.Expressions.MemberExpression'

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

e chiamando come

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

questo funziona bene se la proprietà è di stringa e per tutti gli altri tipi dà questa eccezione:

Impossibile eseguire il cast oggetto di digitare 'System.Linq.Expressions.UnaryExpression' per digitare 'System.Linq.Expressions.MemberExpression'.

  1. ho cambiato stringa di opporsi in firma del metodo, ma poi fallisce di nuovo.
  2. ho cambiato vocazione x => x.PropertyName-x => Convert.ToString(x.PropertyName) e non riesce ancora

Dove sbaglio?

+2

IMO è meglio usare una variante di questo in cui l'helper prende un 'Expression >'. Questo cambia la sintassi del sito di chiamata in 'GetCorrectPropertyName (() => this.Name)', che a mio modo di vedere è sia meglio scrivere (non c'è bisogno di dare il parametro di tipo generico) e meglio leggere ('this.Name' convoglia l'intento estremamente bene). – Jon

+0

@Jon: Buddy sentiti libero di aggiungere la tua risposta. Se migliore della risposta attuale, accetterò sicuramente la tua. –

+0

Non vorrei farlo perché usurperebbe l'intento della tua domanda. Ma puoi facilmente prendere il codice per questo da [qui] (http://compositewpf.codeplex.com/SourceControl/changeset/view/65392#1024364), Microsoft fa esattamente questo in Prism. – Jon

risposta

44

È necessaria una riga separata per estrarre il membro in cui l'espressione di input è un'espressione unaria.

appena convertito questo da VB.Net, quindi potrebbe essere un po 'fuori - fatemi sapere se ho bisogno di fare eventuali piccoli aggiustamenti:

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

Nota che l'espressione di input non restituisca necessariamente la stringa - che ti costringe a leggere solo le proprietà che restituiscono le stringhe.

+4

Ci si chiede perché qualcosa di simile non sia ancora stato incluso nel BCL o in un'estensione. È incredibilmente utile. – BoltClock

+0

Volevo solo sapere come usarlo/chiamarlo per proprietà e metodi (Subs e Function di VB.Net)? –

+0

@NikhilAgrawal: è meglio fare una nuova domanda, fare riferimento a questo e spiegare pienamente le tue richieste. –

4

Dopo questa domanda (sì, io sono OP) ho ricevuto commenti sulla questione dal Jon

e sono arrivato fino a questo

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

Questo è apparently legato alla boxe/unboxing. Le espressioni Lambda che restituiscono tipi di valore che richiedono il pugilato verranno rappresentate come UnariaExpressioni mentre quelle che restituiscono i tipi di riferimento verranno rappresentate come MemberExpressions.

Problemi correlati