Expresión > ¿Cómo puedo obtener el nombre de TValue?

.net c# expression-trees

Pregunta

//ModelFor(person =>person.Name);
public void ModelFor<TModel, TValue>(
    Expression<Func<TModel, TValue>> expression)
{
    //Result should be "Name"
    string nameOfTValue = ????;     
}

Respuesta aceptada

EDITAR : Después de su edición, creo que desea el nombre del miembro involucrado en la expresión, asumiendo, por supuesto, que la expresión es una expresión miembro en primer lugar.

((MemberExpression)expression.Body).Member.Name

Para ser más robusto, puedes hacer:

var memberEx = expression.Body as MemberExpression;

if (memberEx == null)
     throw new ArgumentException("Body not a member-expression.");

string name = memberEx.Member.Name;

(Ya no es relevante):

Para obtener un System.Type que represente el tipo de TValue tipo TValue , puede usar el operador typeof .

Probablemente quieras:

typeof(TValue).Name

Pero también considere las propiedades FullName y AssemblyQualifiedName si es apropiado.

Esto realmente no tiene nada que ver con los árboles de expresión; puede utilizar esta técnica para obtener el tipo de argumento de tipo para cualquier método genérico.


Respuesta popular

@Ani: No creo que esto sea correcto, creo que quiere el nombre del parámetro en la expresión de tipo TValue

Si esto es cierto ... esto funciona solo a un nivel de profundidad, pero podría ser útil de todos modos:

var nameOfTValue = ((MemberExpression)expression.Body).Member.Name; 

Aquí hay una implementación más inteligente que debería poder manejar múltiples niveles:

 public class PropertyName{
    public static string For<T>(
      Expression<Func<T,object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string For(
      Expression<Func<object>> expression){
      var body=expression.Body;
      return GetMemberName(body);
    }
    public static string GetMemberName(
      Expression expression){
      if(expression is MemberExpression){
        var memberExpression=(MemberExpression)expression;
        if(memberExpression.Expression.NodeType==
           ExpressionType.MemberAccess)
          return GetMemberName(memberExpression.Expression)
            +"."+memberExpression.Member.Name;
        return memberExpression.Member.Name;
      }
      if(expression is UnaryExpression){
        var unaryExpression=(UnaryExpression)expression;
        if(unaryExpression.NodeType!=ExpressionType.Convert)
          throw new Exception(string.Format
            ("Cannot interpret member from {0}",expression));
        return GetMemberName(unaryExpression.Operand);
      }
      throw new Exception
        (string.Format("Could not determine member from {0}",expression));
    }
  }

Uso:

var fieldName=PropertyName.For<Customer>(x=>x.Address.Region);
//fieldName==Address.Region

Otro truco, esto se puede combinar muy bien con la reflexión:

public static T Set<T,TProp>(this T o,
   Expression<Func<T,TProp>> field,TProp value){
  var fn=((MemberExpression)field.Body).Member.Name;
  o.GetType().GetProperty(fn).SetValue(o,value,null);
  return o;
}

Permite establecer propiedades directamente con facilidad, puede ser útil para los dispositivos de prueba:

var customer=new Customer("firstName","lastName");
customer.Set(x=>x.Name, "different firstName");


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