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.
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.
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.
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.
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.
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); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With