Hier einige Code, der mit jedem Ausdruck arbeiten ausgelegt ist - in dem Sinne, dass es nicht im Grunde tut Angenommen, Sie übergeben einen Methodenaufruf-Ausdruck. Es ist jedoch nicht vollständig. Sie müssen den Rest ausfüllen.
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();
}
Für den Fall, dass Sie erwähnt haben, funktioniert dies bereits:
// 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);
Für komplexere Lambda-Ausdrücke, die andere Typen von Expressions Knoten verwenden, werden Sie schrittweise den obigen Code erweitern müssen. Jedes Mal, wenn Sie es verwenden, und es wirft ein NotImplementedException
, hier ist das, was ich tue:
- Öffnen Sie das Fenster Uhr im Debugger
- Blick auf die
expression
Variable und den Typ
- den erforderlichen Code hinzufügen zu handhaben dieser Ausdruckstyp
Im Laufe der Zeit wird die Methode immer vollständiger.
@Omu: Aber wollen Sie wirklich Code, der brechen würde - zur Ausführungszeit nur - wenn Sie * any * andere Form von Lambda-Ausdruck verwendet? Wenn Sie immer Save aufrufen, warum übergeben Sie die Parameter nicht einfach direkt? –
@ Jon Skeet, ich werde viele andere Methoden mit verschiedenen Parametern aufrufen, wusste ich nicht, dass ich nur mit konstanten Werten aufrufen kann, ich denke, ich werde dies weiter untersuchen müssen – Omu
@Omu: Dies ist das Problem, wenn man einfach Code in eine Frage ohne Erklärung steckt. Ich habe * sagen * es war spröde, und würde scheitern, sobald Sie anfangen, irgendein anderes Muster zu verwenden ... –