2

When using LINQ Expressions, the C# compiler will conveniently translate C# lambdas into Expression objects:

//using System; //using System.Linq.Expressions; Expression<Func<int, bool>> lambda_expression = (int x) => x == 3; 

This is convenient, and can save a lot of typing versus explicitly constructing the expression:

Expression<Func<int, bool>> explicit_expression_object; { var x = Expression.Parameter(typeof(int), "x"); explicit_expression = Expression.Lambda<Func<int, bool>>(Expression.Equal(x, Expression.Constant(3)), x); } 

However there are situations when it is necessary to use the "longhand" Expression object syntax, for example when dynamically creating expressions at run time. As such, I currently find myself using a mix of "expression lambdas" and dynamically generated "explicit" expression objects.

Is it possible to "include" or "embed" an Expression object into an expression lambda?

For example:

Expression inner_expression_object = Expression.Constant(3); Expression<Func<int, bool>> wrapper_expression = (int x) => x == inner_expression_object.Embed(); 
5
  • Have a look at this (stack-overflow) answer <stackoverflow.com/a/24403382/9204431> Commented Apr 19, 2018 at 10:24
  • Related, almost a duplicate. Spoiler: no, you have to combine them manually. Commented Apr 19, 2018 at 17:37
  • You could write an ExpressionVisitor for this, something like LINQKit has for queries. Commented Apr 19, 2018 at 17:44
  • Note there is no way for Embed to know the proper type so I think you will need Embed<T> to work. Commented Apr 19, 2018 at 17:55
  • Though it would be nice if there were generic variations of Expression objects that provided return types. Commented Apr 19, 2018 at 18:54

1 Answer 1

2

Using an ExpressionVisitor, you can replace calls to an Expression extension method with the Expression.

First, you need an ExpressionVisitor class to expand the Embed method calls to their values:

public class EmbedVisitor : ExpressionVisitor { public override Expression Visit(Expression node) { if (node?.NodeType == ExpressionType.Call) { var callnode = node as MethodCallExpression; if (callnode.Method.Name == "Embed" && callnode.Method.DeclaringType == typeof(ExpressionExt)) return callnode.Arguments[0].Evaluate<Expression>(); } return base.Visit(node); } } 

Then you need a static class for the extension methods needed:

public static class ExpressionExt { public static T Embed<T>(this Expression e) { return default(T); } public static Expression ExpandEmbed(this Expression orig) => new EmbedVisitor().Visit(orig); public static T Evaluate<T>(this Expression e) { //A little optimization for constant expressions if (e.NodeType == ExpressionType.Constant) return (T)((ConstantExpression)e).Value; else return (T)Expression.Lambda(e).Compile().DynamicInvoke(); } } 

Now you can use these to expand embedded Expression valued sub-expressions:

var inner_expression_object = Expression.Constant(3); Expression<Func<int, bool>> wrapper_expression = (int x) => x == inner_expression_object.Embed<int>(); var expanded = wrapper_expression.ExpandEmbed(); // Expression<Func<int,bool>> expanded == (int x) => x == 3; 

You can also directly embed Expression expressions and expand them:

Expression<Func<int,bool>> wrap2 = x => x == Expression.Multiply(Expression.Constant(4), Expression.Constant(8)).Embed<int>(); var expanded2 = wrap2.ExpandEmbed(); // Expression<Func<int,bool>> expanded2 = x => x == 4*8; 
Sign up to request clarification or add additional context in comments.

7 Comments

Liked your solution but I am not clear about various practical use cases, could you please elaborate few
Also is there a good source to learn about Expression trees in depth
Tried using your code like expanded.Evaluate<int>();, but this leads to Invalid cast exception in the following line return (T)Expression.Lambda(e).Compile().DynamicInvoke();
@MrinalKamboj and what was in expanded that would evaluate to an int?
@MrinalKamboj Here is an article on one use case using LINQ to Entities (or SQL).
|