c# - Invoking lambda expressions in Expression trees -


i have selectioncriteria class use building entity framework query expressions, based on predicatebuilder. within limits, it's working fine. i'd extend can query whether field contains substring. problem can't see how build needed expression object.

my actual class supports and, or, , not, aren't relevant question. i've simplified example code handle single binary operation:

public class selectioncriteria {     public selectioncomparison selectioncomparison { get; set; }     public string fieldname { get; set; }     public object fieldvalue { get; set; }      public expression<func<t, bool>> constructsinglepredicate<t>()     {         var type = typeof(t);          if (type.getproperty(this.fieldname) == null && type.getfield(this.fieldname) == null)             throw new missingmemberexception(type.name, this.fieldname);          expressiontype operation;         if (!operationmap.trygetvalue(this.selectioncomparison, out operation))             throw new argumentoutofrangeexception("selectioncomparison", this.selectioncomparison, "invalid filter operation");          var parameter = expression.parameter(type);         var member = expression.propertyorfield(parameter, this.fieldname);         var value = (this.fieldvalue == null) ? expression.constant(null) : expression.constant(this.fieldvalue, this.fieldvalue.gettype());          try         {             var converted = (value.type != member.type)                 ? (expression) expression.convert(value, member.type)                 : (expression) value;              var comparison = expression.makebinary(operation, member, converted);              var lambda = expression.lambda<func<t, bool>>(comparison, parameter);              return lambda;         }         catch (exception)         {             throw new invalidoperationexception(                 string.format("cannot convert value \"{0}\" of type \"{1}\" field \"{2}\" of type \"{3}\"", this.fieldvalue,                     value.type, this.fieldname, member.type));         }     }      private static dictionary<selectioncomparison, expressiontype> operationmap =         new dictionary<selectioncomparison, expressiontype>         {             { selectioncomparison.equal, expressiontype.equal },             { selectioncomparison.greaterthan, expressiontype.greaterthan },         }; }  public enum selectioncomparison {     equal,     greaterthan,     contains, }; 

usage simple:

var criteria = new selectioncriteria {     selectioncomparison = selectioncomparison.greaterthan,     fieldname = "worktobegindate",     fieldvalue = datetime.now.adddays(-2) };  var predicate = criteria .constructpredicate<job>(); var jobs = mydbcontext.jobs.where(predicate); 

so, problem - need method, constructsinglepredictate() above, returns expression> , applies .contains(

it's trivial apply contains() string, given string compare to, i'm having difficulty figuring out how same in expression.

ideas?

as usual, thinking things incorrectly. don't need lambda calls method on string, need methodexpression (here extracted methodmap dictionary):

public expression<func<t, bool>> constructmethodcallpredicate<t>() {     var type = typeof(t);      if (type.getproperty(this.fieldname) == null && type.getfield(this.fieldname) == null)         throw new missingmemberexception(type.name, this.fieldname);      methodinfo method;     if (!methodmap.trygetvalue(this.selectioncomparison, out method))         throw new argumentoutofrangeexception("selectioncomparison", this.selectioncomparison, "invalid filter operation");      var parameter = expression.parameter(type);     var member = expression.propertyorfield(parameter, this.fieldname);     var value = (this.fieldvalue == null) ? expression.constant(null) : expression.constant(this.fieldvalue, this.fieldvalue.gettype());      try     {         var converted = (value.type != member.type)             ? (expression)expression.convert(value, member.type)             : (expression)value;          var methodexpression = expression.call(member, method, converted);          var lambda = expression.lambda<func<t, bool>>(methodexpression, parameter);          return lambda;     }     catch (exception)     {         throw new invalidoperationexception(             string.format("cannot convert value \"{0}\" of type \"{1}\" field \"{2}\" of type \"{3}\"", this.fieldvalue,                 value.type, this.fieldname, member.type));     } }  private static readonly dictionary<selectioncomparison, methodinfo> methodmap =     new dictionary<selectioncomparison, methodinfo>     {         { selectioncomparison.contains, typeof(string).getmethod("contains", new[] { typeof(string) }) },         { selectioncomparison.startswith, typeof(string).getmethod("startswith", new[] { typeof(string) }) },         { selectioncomparison.endswith, typeof(string).getmethod("endswith", new[] { typeof(string) }) },     };  public enum selectioncomparison {     equal,     notequal,     lessthan,     lessthanorequal,     greaterthan,     greaterthanorequal,     contains,     startswith,     endswith, }; 

getting actual "like" comparison work, using sqlfunctions.patindex bit more complicated, patindex() returns int, , need wrap in >0 expression, works fine, well.


Comments

Popular posts from this blog

javascript - RequestAnimationFrame not working when exiting fullscreen switching space on Safari -

Python ctypes access violation with const pointer arguments -