Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I create an expression tree to represent 'String.Contains("term")' in C#?

I am just getting started with expression trees so I hope this makes sense. I am trying to create an expression tree to represent:

t => t.SomeProperty.Contains("stringValue"); 

So far I have got:

    private static Expression.Lambda<Func<string, bool>> GetContainsExpression<T>(string propertyName, string propertyValue)     {         var parameterExp = Expression.Parameter(typeof(T), "type");         var propertyExp = Expression.Property(parameter, propertyName);         var containsMethodExp = Expression.*SomeMemberReferenceFunction*("Contains", propertyExp) //this is where I got lost, obviously :)         ...         return Expression.Lambda<Func<string, bool>>(containsMethodExp, parameterExp); //then something like this     } 

I just don't know how to reference the String.Contains() method.

Help appreciated.

like image 611
flesh Avatar asked Nov 10 '08 18:11

flesh


People also ask

What is the use of expression tree in C#?

Expression trees represent code in a tree-like data structure, where each node is an expression, for example, a method call or a binary operation such as x < y . You can compile and run code represented by expression trees.

What is query expression trees?

Expression tree is an in-memory representation of a lambda expression. It holds the actual elements of the query, not the result of the query. The expression tree makes the structure of the lambda expression transparent and explicit.

What are the advantages of expression tree?

Expression trees allow you to build code dynamically at runtime instead of statically typing it in the IDE and using a compiler. They are well explained in the documentation.


2 Answers

Something like:

class Foo {     public string Bar { get; set; } } static void Main() {     var lambda = GetExpression<Foo>("Bar", "abc");     Foo foo = new Foo { Bar = "aabca" };     bool test = lambda.Compile()(foo); } static Expression<Func<T, bool>> GetExpression<T>(string propertyName, string propertyValue) {     var parameterExp = Expression.Parameter(typeof(T), "type");     var propertyExp = Expression.Property(parameterExp, propertyName);     MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) });     var someValue = Expression.Constant(propertyValue, typeof(string));     var containsMethodExp = Expression.Call(propertyExp, method, someValue);      return Expression.Lambda<Func<T, bool>>(containsMethodExp, parameterExp); } 

You might find this helpful.

like image 118
Marc Gravell Avatar answered Oct 26 '22 22:10

Marc Gravell


To perform a search like:

ef.Entities.Where(entity => arr.Contains(entity.Name)).ToArray(); 

which the trace string will be:

SELECT .... From Entities ... Where Name In ("abc", "def", "qaz") 

I use the method I created below:

ef.Entities.Where(ContainsPredicate<Entity, string>(arr, "Name")).ToArray();  public Expression<Func<TEntity, bool>> ContainsPredicate<TEntity, T>(T[] arr, string fieldname) where TEntity : class {   ParameterExpression entity = Expression.Parameter(typeof(TEntity), "entity");   MemberExpression member = Expression.Property(entity, fieldname);    var containsMethods = typeof(Enumerable).GetMethods(BindingFlags.Static | BindingFlags.Public)   .Where(m => m.Name == "Contains");   MethodInfo method = null;   foreach (var m in containsMethods) {     if (m.GetParameters().Count() == 2) {       method = m;       break;     }   }   method = method.MakeGenericMethod(member.Type);   var exprContains = Expression.Call(method, new Expression[] { Expression.Constant(arr), member });   return Expression.Lambda<Func<TEntity, bool>>(exprContains, entity); } 
like image 27
Leng Weh Seng Avatar answered Oct 26 '22 23:10

Leng Weh Seng