c# - Extract all conditions from Expression by Type -


given expression<func<tentity, bool>> along lines of

entity => entity.subentity.any(     subentity => (         (subentity.someproperty == false)         andalso         subentity.subsubentity.fooproperty.startswith(             value(someclass+<>c__displayclass0).comparisonproperty         )         andalso         subentity.subsubentity.barproperty == "bar"         andalso         subentity.subsubentity.subsubsubentity.any(             subsubsubentity => (x.subsubsubsubentity.bazproperty == "whatever")         )     ) ) 

i trying extract list property conditions type, i.e.

tentity             : [ /* no conditions immediate members of tentity */ ]  tsubentity          : [ { someproperty == false } ] tsubsubentity       : [ { fooproperty.startswith(/* ... */) },                         { barproperty == "bar" } ], tsubsubsubentity    : [ /* no conditions immediate members of tsubsubsubentity */ ], tsubsubsubsubentity : [ { bazproperty == "whatever" } ] 

so far, have created expressionvisitor , identified visitbinary method 1 want plug in order obtain information.

i still @ loss about

  • how determine whether binaryexpression looking @ represents terminal statement (in sense there no more nested expressions need at)
  • how determine entity type binaryexpression concerned with
  • whether need override of other expressionvisitor methods cover cases have not considered yet.

not sure use case, here starting point

class testvisitor : expressionvisitor {     public dictionary<type, list<tuple<memberexpression, expression>>> result = new dictionary<type, list<tuple<memberexpression, expression>>>();     stack<expression> stack = new stack<expression>();     public override expression visit(expression node)     {         stack.push(node);         base.visit(node);         stack.pop();         return node;     }     protected override expression visitmember(memberexpression node)     {         if (node.expression.nodetype != expressiontype.constant && (node.type == typeof(string) || !typeof(ienumerable).isassignablefrom(node.type)))         {             var expression = stack.skip(1).firstordefault();             if (expression != null && expression.type == typeof(bool))             {                 list<tuple<memberexpression, expression>> resultlist;                 if (!result.trygetvalue(node.expression.type, out resultlist))                     result.add(node.expression.type, resultlist = new list<tuple<memberexpression, expression>>());                 resultlist.add(tuple.create(node, expression));             }         }         return base.visitmember(node);     } } 

the idea simple. override visit method maintain stack of processing expressions. main processing inside visitmember override, called each property/field accessor. node.expression.nodetype != expressiontype.constant used eliminate closure members, while second condition eliminates collection properties. finally, potential condition expression extracted stack.

the result including both memberexpression , expression used. memberexpression.expression.type entity type, memberexpression.member property/field of type.

sample test:

class entity {     public icollection<subentity> subentity { get; set; } }  class subentity {     public bool someproperty { get; set; }     public subsubentity subsubentity { get; set; } }  class subsubentity {     public string fooproperty { get; set; }     public string barproperty { get; set; }     public icollection<subsubsubentity> subsubsubentity { get; set; } }  class subsubsubentity {     public subsubsubsubentity subsubsubsubentity { get; set; } }  class subsubsubsubentity {     public string bazproperty { get; set; } }  class program {     static void main(string[] args)     {         string comparisonproperty = "ivan";         expression<func<entity, bool>> e =             entity => entity.subentity.any(subentity =>                 subentity.someproperty == false                 &&                 subentity.subsubentity.fooproperty.startswith(comparisonproperty)                 &&                 subentity.subsubentity.barproperty == "bar"                 &&                 subentity.subsubentity.subsubsubentity.any(subsubsubentity => subsubsubentity.subsubsubsubentity.bazproperty == "whatever")                 );         var v = new testvisitor();         v.visit(e);         var result = v.result;     } } 

Comments

Popular posts from this blog

php - Wordpress website dashboard page or post editor content is not showing but front end data is showing properly -

javascript - Get parameter of GET request -

javascript - Twitter Bootstrap - how to add some more margin between tooltip popup and element -