2017-10-21 70 views
1

J'ai créé cette expression dans un code:expression `t => (t.SomeProperty As Object)` fait référence à une méthode, pas une propriété

t => (t.SomeProperty As Object) 

et maintenant je suis en train d'obtenir la propriété -nom (SomeProperty) par ce petit extrait (obtenu à partir d'Internet depuis longtemps moi):

public static PropertyInfo GetPropertyInfo<TSource, TProperty> 
     (TSource source, Expression<Func<TSource, TProperty>> propertyLambda) { 
     var type = typeof(TSource); 

     var member = propertyLambda.Body as MemberExpression; 
     if (member == null) 
      throw new ArgumentException($"Expression '{propertyLambda}' refers to a method, not a property."); 

     var propInfo = member.Member as PropertyInfo; 
     if (propInfo == null) 
      throw new ArgumentException($"Expression '{propertyLambda}' refers to a field, not a property."); 

     if (type != propInfo.ReflectedType && !type.IsSubclassOf(propInfo.ReflectedType)) 
      throw new ArgumentException($"Expresion '{propertyLambda}' refers to a property that is not from type {type}."); 

     return propInfo; 
    } 

Mais comme vous le savez, propertyLambda.Body as MemberExpression est toujours nulle, parce que ceci: t => (t.Some1 As Object) n'est pas une propriété se réfèrent. Est-il possible d'obtenir le nom de la propriété dans ce cas?

Répondre

4

C# as opérateur se traduit par Expression.TypeAs et C# opérateurs de la distribution traduire soit Expression.Convert ou Expression.ConvertChecked. Comme vous pouvez le voir, ils sont tous de type UnaryExpression, d'où vous pouvez extraire l'expression de l'opérande en utilisant la propriété Operand. Et vous pouvez le faire en boucle afin de supporter plusieurs lancers.

mettre en action, remplacer

var member = propertyLambda.Body as MemberExpression; 

avec

var operand = propertyLambda.Body; 
while (operand.NodeType == ExpressionType.TypeAs || operand.NodeType == ExpressionType.Convert || operand.NodeType == ExpressionType.ConvertChecked) 
    operand = ((UnaryExpression)operand).Operand; 
var member = operand as MemberExpression; 
0

Je recommande ceci:

PropertyInfo info = t.GetType().GetProperty("SomeProperty", 
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); 
// Use these binding flags to get a member of any visibility. 

Il retourne un PropertyInfo pour une propriété d'un nom donné.

Si vous ne voulez pas gérer le nom explicitement, utilisez nameof(t.SomeProperty).

Vous pouvez également trouver la méthode .GetProperties utile pour obtenir toutes les propriétés d'un type spécifique.

1

Dans votre cas, vous devez regarder l'opérande de l'expression unaire qui est la distribution.

((propertyLamdba.Body as UnaryExpression).Operand as MemberExpression).Member 

Pour le rendre plus sûr par programme, vous devriez vérifier votre propriétéLamba. Quelque chose comme:

if (propertyLamdba.Body.NodeType == ExpressionType.TypeAs) 
    member = ((propertyLamdba.Body as UnaryExpression).Operand as MemberExpression).Member