Aquí hay un código que está diseñado para trabajar con cualquier expresión - en el sentido de que no lo hace, fundamentalmente, supongamos que está pasando una expresión de llamada a método. Sin embargo, no está completo. Tendrás que completar el resto.
public static IEnumerable<object> ExtractConstants<T>(
Expression<Action<T>> expression)
{
return extractConstants(expression);
}
private static IEnumerable<object> extractConstants(Expression expression)
{
if (expression == null)
yield break;
if (expression is ConstantExpression)
yield return ((ConstantExpression) expression).Value;
else if (expression is LambdaExpression)
foreach (var constant in extractConstants(
((LambdaExpression) expression).Body))
yield return constant;
else if (expression is UnaryExpression)
foreach (var constant in extractConstants(
((UnaryExpression) expression).Operand))
yield return constant;
else if (expression is MethodCallExpression)
{
foreach (var arg in ((MethodCallExpression) expression).Arguments)
foreach (var constant in extractConstants(arg))
yield return constant;
foreach (var constant in extractConstants(
((MethodCallExpression) expression).Object))
yield return constant;
}
else
throw new NotImplementedException();
}
Para el caso de que usted ha mencionado, esto ya funciona:
// Prints:
// Jimmy (System.String)
// 1 (System.Int32)
foreach (var constant in Ext.ExtractConstants<string>(
str => Console.WriteLine("Jimmy", 1)))
Console.WriteLine("{0} ({1})", constant.ToString(),
constant.GetType().FullName);
Para las expresiones lambda más complejas que emplean otros tipos de nodos de expresión, que tendrá que extender gradualmente el código de seguridad. Cada vez que lo utilice y se lanza una NotImplementedException
, esto es lo que hago:
- Abra la ventana de inspección en el depurador
- mirada a la variable
expression
y su tipo
- Añadir el código necesario para manejar ese tipo de expresión
Con el tiempo, el método será cada vez más completo.
@Omu: ¿Pero realmente quieres un código que se rompa, solo en el momento de la ejecución, si usaste * any * otra forma de expresión lambda? Si * siempre * va a llamar a Guardar, ¿por qué no pasa los parámetros directamente? –
@Jon Skeet, voy a llamar a muchos otros métodos con diferentes parámetros, no sabía que solo puedo llamar con valores constantes, supongo que voy a tener que investigar esto más – Omu
@Omu: Este es el problema con solo el código de dumping en una pregunta sin explicación. Dije * que era frágil y fallaría tan pronto como comenzaras a usar cualquier otro patrón ... –