linq - Currying Expressions in C# -


i trying build expression tree can feed linq2sql generate nice clean query. purpose build filter takes arbitrary set of words , and not (or or , not) together. because want vary fields search on preferably want compose list of expresssion<func<t, string, bool>>'s (where t entity operating on) calling variety of helper functions. receive array of words , loop though them , build expresssion<func<t, bool>> (negating expressions necessary) can feed .where statement.

i have been using linqkit predicatebuilder code deals single parameter expressions. however, has provided me groundwork own attempts. aiming this:

var e = (expression<func<entity, string, bool>>)((p, w) => p.somefield.tolower().contains(w));  var words = new []{"amanda", "bob"};  var expr = (expression<func<entity, bool>>)(p => false); // building or query foreach(var w in words) {     var w1 = w; >>>>expr = expression.lambda<func<entity, bool>>(expression.orelse(expr.body, (expression<func<entity, bool>>)(p => e(p, w)))); }  var filteredentities = table.where(expr); 

but since using expressions line marked >>>> illegal (cannot e(p, w) function). question how do partial application of single variable (the word) expressions containing functions multiple parameters?


okay, fiddled around in linqpad , figured out solution works me. this question got me there. pretty new building expression trees appreciate (and upvote) comments/answers improvements or criticism.

// set of expressions test against var expressions = new list<expression<func<entity, string, bool>>>(); expressions.add((p, w) => p.firstname.tolower().contains(w)); expressions.add((p, w) => p.lastname.tolower().contains(w)); expressions.add((p, w) => p.department != null && p.department.name.tolower().contains(w));  var words = new []{"amanda", "bob"}; var negs = new []{"smith"}; // exclude entries including these words  var isandquery = true; // negate or query expression<func<entity, bool>> posexpr = p => isandquery;  var entityparameter = expression.parameter(typeof(entity), null);  // build nots var negexpr = (expression<func<entity, bool>>)(p => true); foreach(var w in negs) {     var w1 = w;     foreach(var e in expressions) {         var andnot = expression.invoke(e, entityparameter, expression.constant(w1));         negexpr = expression.lambda<func<entity, bool>>(expression.andalso(negexpr.body, expression.not(andnot)), entityparameter);     } }  // build ands or ors foreach(var w in words) {     var w1 = w;     var orexpr = (expression<func<entity, bool>>)(p => false);     foreach(var e in expressions) {         var orelse = expression.invoke(e, entityparameter, expression.constant(w1));         orexpr = expression.lambda<func<entity, bool>>(expression.orelse(orexpr.body, orelse), entityparameter);     }     var orinvoked = expression.invoke(orexpr, posexpr.parameters.cast<expression>());     if(isandquery)         posexpr = expression.lambda<func<entity, bool>>(expression.andalso(posexpr.body, orinvoked), entityparameter);     else         posexpr = expression.lambda<func<entity, bool>>(expression.orelse(posexpr.body, orinvoked), entityparameter); } var posinvoked = expression.invoke(posexpr, posexpr.parameters.cast<expression>()); var finalexpr = expression.lambda<func<entity, bool>>(expression.andalso(negexpr.body, posinvoked), entityparameter);  var filteredentities = entities.where(finalexpr); 

this example might you. guess best build expression without lambdas:

public class entity {     public entity(string somefield)     {         somefield = somefield;     }      public string somefield { get; set;  } }  class program {     static void main(string[] args)     {         var entities = new[] {new entity("foobar"), new entity("barbaz"), new entity("baz"), new entity("foo")};         entities.where(buildexpression("ar","az").compile())                 .tolist()                 .foreach(e => console.writeline(e.somefield));         console.readline();     }      public static expression<func<entity, bool>> buildexpression(params string[] words)     {         var parameter = expression.parameter(typeof (entity));          var matchs = words.select(word =>                                         {                                             var property = expression.property(parameter, "somefield");                                             var tolower = expression.call(property, "tolower", new type[] {});                                             var contains = expression.call(tolower, "contains",                                                                             new type[]{},                                                                             expression.constant(word));                                             return contains;                                         }).oftype<expression>();          var body = matchs.aggregate(expression.or);          return expression.lambda<func<entity, bool>>(body, new[] {parameter});     }  } 

please let me know if should add more information answer.


Comments

Popular posts from this blog

php - What is the difference between $_SERVER['PATH_INFO'] and $_SERVER['ORIG_PATH_INFO']? -

fortran - Function return type mismatch -

queue - mq_receive: message too long -