Вот некоторый код, который предназначен для работы с любым выражением - в том смысле, что он не предполагает, что вы передаете выражение вызова метода.Тем не менее, это не завершено.Остальное вам нужно будет заполнить.
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();
}
В случае, который вы упомянули, это уже работает:
// 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);
Для более сложных лямбда-выражений, которые используют другие типы выраженийузлы, вам придется постепенно расширять вышеуказанный код.Каждый раз, когда вы используете его, и он выдает NotImplementedException
, вот что я делаю:
- Откройте окно просмотра в отладчике
- Посмотрите на переменную
expression
и еевведите - Добавьте необходимый код для обработки этого типа выражения
Со временем метод будет становиться все более и более полным.