Frage

Ich habe einen Ausdruck Baum, den ich durch Parsen einer XML-unter Verwendung des Ausdrucks Klasse in C # erstellt haben. Sehen Sie diese Frage .

ich nur haben zu Addieren, Subtrahieren, Dividieren, Multiplizieren, Parameter und und Oder in meinem Ausdruck Baum. Gibt es eine Möglichkeit, diese ExpressionTree in eine aufrufbare Methode zu konvertieren? ... oder muss ich manuell die IL emittieren?

Mit freundlichen Grüßen

War es hilfreich?

Lösung

Hier ist ein Beispiel der beiden Ansätze. Wenn ich etwas verpasst haben, oder Sie weitere Informationen wünschen, lassen Sie es mich wissen.

static void Main()
{
    // try to do "x + (3 * x)"

    var single = BuildSingle<decimal>();
    var composite = BuildComposite<decimal>();

    Console.WriteLine("{0} vs {1}", single(13.2M), composite(13.2M));
}
// utility method to get the 3 as the correct type, since there is not always a "int x T"
static Expression ConvertConstant<TSource, TDestination>(TSource value)
{
    return Expression.Convert(Expression.Constant(value, typeof(TSource)), typeof(TDestination));
}
// option 1: a single expression tree; this is the most efficient
static Func<T,T> BuildSingle<T>()
{        
    var param = Expression.Parameter(typeof(T), "x");
    Expression body = Expression.Add(param, Expression.Multiply(
        ConvertConstant<int, T>(3), param));
    var lambda = Expression.Lambda<Func<T, T>>(body, param);
    return lambda.Compile();
}
// option 2: nested expression trees:
static Func<T, T> BuildComposite<T>()
{

    // step 1: do the multiply:
    var paramInner = Expression.Parameter(typeof(T), "inner");
    Expression bodyInner = Expression.Multiply(
        ConvertConstant<int, T>(3), paramInner);
    var lambdaInner = Expression.Lambda(bodyInner, paramInner);

    // step 2: do the add, invoking the existing tree
    var paramOuter = Expression.Parameter(typeof(T), "outer");
    Expression bodyOuter = Expression.Add(paramOuter, Expression.Invoke(lambdaInner, paramOuter));
    var lambdaOuter = Expression.Lambda<Func<T, T>>(bodyOuter, paramOuter);

    return lambdaOuter.Compile();
}

Ich persönlich würde auf dem ersten Verfahren zielt darauf ab; es sich einfacher und effizienter zu gestalten. Dies kann die ursprünglichen Parameter über einen Stapel von verschachteltem Code beinhaltet vorbei, aber es so sein. Ich habe einige Code irgendwo bekam, dass die „Invoke“ -Ansatz (Composite) nimmt und wieder schreibt den Baum als der erste Ansatz (single) - aber es ist recht komplex und lang. Aber sehr nützlich für die Framework-Entity (die Expression.Invoke nicht unterstützt).

Andere Tipps

Sie benötigen ein Lambda erstellen - d. H

var lambda = Expression.Lambda<Func<float,int>>(body, param);
Func<float,int> method = lambda.Compile();
int v = method(1.0); // test

Dabei steht "Körper" ist Ihr Ausdrucksbaum (unter einem Schwimmer, die Rückkehr einen int) Beteiligung des ParameterExpression param.

Sie können auch finden diese und diese hilfreich.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top