dynamic - Expression and delegate in c# -
i have below code pseudo-code. want make function can accept expresstion type, compile expression , invoke proper parameters.
public static void f<t>(expression<t> exp, params dynamic[] d) { console.writeline("begin"); exp.compile().invoke(d[0],d[1].....);//this pseudo-code console.writeline("end"); } i'm sure t action type. (t can action,action<int>,etc.). parameter d array of dynamic type, sent invoke.
but don't know how finish code. i'm sure that's not easy implement it. perhaps can't true in c#
you can't use invoke unless know exact signature. can, however, use dynamicinvoke, example:
((delegate)exp.compile()).dynamicinvoke(d); note dynamic in above serves no purpose - d object[].
the other, more complicated, approach - compile func<object[]>, , re-write expression (expressionvisitor) replace "parameter n" (from original exp) p[n], p single parameterexpression , n constantexpression of n. might advantageous if going store , aggressively re-use compiled lambda. in specific scenario compiling per call, have no benefit.
here's example, intended later readers similar scenarios, compiled delegate re-used; "advantage" of re-writing avoids performance impact of delegate.dynamicinvoke, while retaining object[] => object signature of delegate.dynamicinvoke; useful if delegate being used multiple times. @ moment (compiled per call) of "work" here going in expression-compile , jit-compile.
using system; using system.collections.generic; using system.linq.expressions; static class program { static void main() { expression<func<int, float, double>> exp = (i, f) => * f; var func = compiletobasictype(exp); object[] args = { 3, 2.3f }; object result = func(args); // 6.9 (double) } static func<object[], object> compiletobasictype(lambdaexpression exp) { parameterexpression arg = expression.parameter(typeof(object[]), "args"); dictionary<expression, expression> lookup = new dictionary<expression, expression>(); int = 0; foreach (var p in exp.parameters) { lookup.add(p, expression.convert(expression.arrayindex( arg, expression.constant(i++)), p.type)); } var body = expression.convert( new replacevisitor(lookup).visit(exp.body), typeof(object)); return expression.lambda<func<object[], object>>(body, arg).compile(); } class replacevisitor : expressionvisitor { private readonly dictionary<expression, expression> lookup; public replacevisitor(dictionary<expression, expression> lookup) { if (lookup == null) throw new argumentnullexception("lookup"); this.lookup= lookup; } public override expression visit(expression node) { expression found; return lookup.trygetvalue(node, out found) ? found : base.visit(node); } } }
Comments
Post a Comment