Dada una expresión lambda de acceso de miembros, conviértala en una representación de cadena específica con ruta de acceso completa

Dado un

Expression<Func> 

(por ejemplo, x => x.Prop1.SubProp), quiero crear una cadena “Prop1.SubProp” para la profundidad necesaria.

En el caso de un acceso único (por ejemplo, x => x.Prop1), puedo hacer esto fácilmente con:

 MemberExpression body = (expression.Body.NodeType == ExpressionType.Convert) ? (MemberExpression)((UnaryExpression)expression.Body).Operand : (MemberExpression)expression.Body; return body.Member.Name; 

Sin embargo, si hay un anidamiento más profundo, por ejemplo, x => x.Prop1.SubProp1, solo se obtiene el nombre más profundamente nested, por ejemplo, “SubProp1” en lugar de “Prop1.SubProp1”

¿Hay alguna forma de acceder a la ruta de propiedad completa de una expresión lambda?

 public string GetPath(Expression> expr) { var stack = new Stack(); MemberExpression me; switch (expr.Body.NodeType) { case ExpressionType.Convert: case ExpressionType.ConvertChecked: var ue = expr.Body as UnaryExpression; me = ((ue != null) ? ue.Operand : null) as MemberExpression; break; default: me = expr.Body as MemberExpression; break; } while (me != null) { stack.Push(me.Member.Name); me = me.Expression as MemberExpression; } return string.Join(".", stack.ToArray()); } 

Eche un vistazo a mi respuesta a esta pregunta .

Más o menos lo mismo que publicó LukeH, con una característica adicional:

Si tiene un tipo, digamos, MyClass , con una propiedad MyProperty de tipo int , podría escribir esto:

 Expression> e = x => x.MyProperty; 

Aquí, la expresión e.Body no es una MemberExpression por lo que el simple while (me != null) me = me.Expression as MemberExpression no funcionará.

La solución es verificar adicionalmente si se trata de una UnaryExpression con NodeType == Convert o ConvertChecked .

Puede haber otros escenarios a tener en cuenta; pero para cadenas simples de expresiones de propiedad, este enfoque funciona bastante bien.

Puedes usar un proyecto que he creado para convertir lambda a javascript: lambda2js

Cuando use solo propiedades e indexadores, el resultado debe ser exactamente lo que necesita.

Ejemplo 1: ruta de propiedad única

 Expression> expr = x => x.Phone; var js = expr.CompileToJavascript(); // returns: Phone 

Ejemplo 2: Ruta que contiene el indexador de un diccionario de cadenas

 Expression> expr = x => x.PhonesByName["Miguel"]; var js = expr.CompileToJavascript(); // returns: PhonesByName["Miguel"] 

Ejemplo 3: Ruta compleja que contiene indexadores y niveles múltiples

 Expression> expr = x => x.SomeProp["Miguel"].Subprop[0].AB; var js = expr.CompileToJavascript(); // returns: SomeProp["Miguel"].Subprop[0].AB