c# - System.Linq.Dynamic.DynamicExpression parsing expressions with methods -
i need build system have number of expressions stored in file. these expressions read program, compiled linq expressions , evaluated functions on number of objects. however, these expressions contain references functions in code (i.e. not made of basic c# operators).
i'm trying use dynamicexpression system.linq.dynamic , works, except functions code not recognized. basically, when have code below:
public class geoobj { public int layer; public polygon poly; } class program { public static bool complicatedmethod(geoobj x, geoobj y) { bool result = // quite complicated computation on x , y, polygon intersection test return result; } static void main(string[] args) { geoobj o1 = new geoobj(); // here set o1 fields geoobj o2 = new geoobj(); // here set o2 fields string sexpr = @"(x.layer == y.layer) && (complicatedmethod(x,y))"; var xparam = expression.parameter(typeof(geoobj), "x"); var yparam = expression.parameter(typeof(geoobj), "y"); expression<func<geoobj, geoobj, bool>> expr = (expression<func<geoobj, geoobj, bool>>)system.linq.dynamic.dynamicexpression.parselambda(new[] { xparam, yparam }, typeof(bool), sexpr); var del2 = expr.compile(); console.writeline(del2(o1, o2)); } }
(of course, in final version, sexpr read text file, example.)
the code throws exception @ parselambda, stating "complicatedfunction" not known. can see how parselambda not know "complicatedfunction" because not know in assembly it's used.
is there way compile string actual expression? if create expression in code using hard-coded this:
expression<func<geoobj, geoobj, bool>> expr = (x, y) => (x.layer == y.layer) && complicatedfunction(x,y));
it works intended, cannot anticipate possible expressions.
if it's not possible, suppose next best thing parse string expressions parse tree, , create expression tree. since there few functions (like "complicatedfunction") used, looks doable. best way/best code create syntax tree such expression? need not throw exceptions when symbol not known (like "complicatedfunction") , make easy me to parse tree build expression.
thank you.
-------------------- update ---------------------------------
@pil0t 's answer put me on right track solving this. basically, have download original source file dynamic linq , make 2 modifications.
look for:
static readonly type[] predefinedtypes = {
and remove 'readonly' keyword (so can modified).
then, add following function expressionparser class:
public static void addpredefinedtype(type type) { predefinedtypes = predefinedtypes.union(new[] { type }).toarray(); keywords = expressionparser.createkeywords(); }
you can use new function this:
using system.linq.dynamic; ... expressionparser.addpredefinedtype(typeof(geoobj));
one note syntax expressions though. newly added function give access methods of class 'geoobj' (or whatever class use), , those. means you'll have modify expression follows:
class geoobj { public bool field1; public bool method1() { /* return */ } public static complicatedmethod(geoobj o1, geoobj o2) { ... } } ... string myexpr = @"x.field1 && y.method1() && geoobj.complicatedmethod(x,y)";
in other words, functions need use need moved inside class, @shlomo hinted at. would've liked cleaner notation (e.g. use "complicatedmethod(x,y)" instead of "geoobj.complicatedmethod(x,y)", or have method1(x) instead of x.method1()), these aesthetic preferences @ point. besides, since number of such methods can used small, expressions can rewritten internally go function-call-like-expressions method calls.
thanks pointing me in right direction.
i have done patching original sources with
public class foo { ... public static void addpredefinedtype(type type) { expressionparser.predefinedtypes = expressionparser.predefinedtypes.union(new[] { type }).toarray(); expressionparser.createkeywords(); } }
after this, use
foo.addpredefinedtype(typeof(program));
and methods program available
Comments
Post a Comment