J'ai créé une méthode en 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'appeler 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 une chaîne et pour tous les autres types donne cette exception:
Impossible de convertir un objet de type "System.Linq.Expressions.UnaryExpression" en type "System.Linq.Expressions.MemberExpression".
x => x.PropertyName
En x => Convert.ToString(x.PropertyName)
et il échoue toujoursOù ai-je tort?
Vous avez besoin d'une ligne distincte pour extraire le membre où l'expression d'entrée est une expression unaire.
Je viens de convertir cela à partir de VB.Net, donc cela pourrait être légèrement désactivé - faites-moi savoir 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 - cela vous oblige à lire uniquement les propriétés qui renvoient des chaînes.
C'est apparemment lié à la boxe/unboxing. Les expressions lambda renvoyant des types de valeur qui nécessitent une boxe seront représentées comme UnaryExpressions tandis que celles qui renvoient des types de référence seront représentées comme MemberExpressions.
Après avoir posé cette question (oui je suis OP), j'ai reçu des commentaires sur la question de Jon
et je suis venu avec cette
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;
}
}