Linq Expressions – From and to delegates
I’m getting quite a few hits on my blog regarding Linq Expressions and how to convert those to and from delegates, so I figure I can just as well make a small post about it.
From Delegate to Expression;
This is not really possible, you can never cast or convert an existing delegate into an expression tree.
You can however assign lambda expressions to expression trees exactly the same way as you assign them to a delegate.
//assign a lambda expression to a delegate Func<int> myDelegate = () => 1 + 2 + a +b; or: //assign a lambda expression to an expression tree Expression<Func<int>> myExpressionTree = () => 1 + 2 + a +b;
Notice that you do exactly the same thing, except that the expression tree version wraps the delegate type inside a generic expression class.
The C# compiler will figure out what your intentions are and compile the code in completely different ways for those two cases.
This is the reason why you can not use “var” as the type for a lambda assignment, the compiler have no way to figure out if you want a delegate or an expression tree, or even what type the delegate should have.
The first case will generate an anonymous method that is assigned to the delegate var “myDelegate”.
While the expression tree version will complile the expression into code that builds the expression tree and then asigns the result to the Expression var “myExpressionTree”.
You can also pass lambda expressions exactly the same way;
//pass a lambda expression as a delegate
Foo( () => 1 + 2 + a +b );
....
void Foo (Func<int> myExpressionTree)
{..}
or:
//pass a lambda expression as an expression tree
Foo( () => 1 + 2 + a +b );
....
void Foo (Expression<Func<int>> myExpressionTree)
{..}
Note that the calling code looks exactly the same in both cases, it is only the definition of the methods that are called that differs.
This is also how Linq to Objects and Linq to SQL works.
The Linq to Objects provider uses delegates, while the Linq to SQL provider receives expression trees that are later converted into ad hoc SQL statements.
So in short, the compiler can compile the same expressions into two different forms, but you can not cast or convert from a delegate into an expression tree.
From Expression to Delegate;
Linq expression can not be casted or converted into delegates, they can however be “compiled” into delegates.
eg:
//create an linq expression Expression<Func<int>> myExpressionTree = () => 1 + 2 + a +b; //compile the expression into a delegate Func<int> myDelegate = myExpression.Compile();
The above code is ofcourse useless, you should of course not create expressions and then immediately compile them into delegates.
That would be silly since you could assign the lambda into a delegate directly.
However, there are cases where you might want to add code in between the creation of the expression and the delegate compilation.
eg. you might want to analyze the expression and take certain actions depending on the contents of the expression tree and if some criteria is met, compile the delegate.
The most common reason why you would want to compile linq expressions into delegates is however a completely different story.
Since .NET 3.5 , there are a complete namespace of expression classes.
You can manually build expression trees using those classes and call compile on that tree in order to compile it into CIL code.
This means that you can use the Linq Expression trees as the foundation of a simple compiler.
And as of .NET 4.0, we are getting even more power for our expression trees, the entire Dynamic Language Runtime is build around the Linq Expressions.
So you can build expression trees containing if statements, for loops, variable declarations, assignments etc etc.
But more about that in another post :-)
//Roger
Design by
I have developed an expression tree visualizer that generates it as a graph (or a real tree — not a treeview) on a WPF canvas.
The source of the test program is @ sixpairs.com (not the sources to the libraries though); you can play around with it using any type of C# expression.
The interface is pretty simple:
ExpressionTree.Display(expr) –> Canvas
The canvas will contain a graphviz-based graph rendered in WPF (you don’t need to install graphviz; it does not use the dot notation or the corresponding console utilities in an external process).
Ceyhun Ciper
March 28, 2009 at 4:30 pm
(not sure if my comment went through…)
To take a delegate and create an expression tree, you could attempt to fetch the delegate’s method body, then parse the IL. You’ll need to interpret it into suitable expression trees, which means you’re interpreting the IL to determine what’s going on, but nothing more than what Reflector or FxCop are in the business of doing.
See:
http://msdn.microsoft.com/en-us/library/system.delegate.getmethodimpl.aspx
http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody.aspx
http://msdn.microsoft.com/en-us/library/system.reflection.methodbody.aspx
Keith J. Farmer
April 14, 2009 at 7:35 am
Of course, what I describe probably runs afoul of Full vs Partial Trust requirements. :)
Keith J. Farmer
April 14, 2009 at 7:36 am
@Keith
>>To take a delegate and create an expression tree, you could attempt to fetch the delegate’s method
>>body, then parse the IL. You’ll need to interpret it into suitable expression trees
Yes, that will be doable in .NET 4 when the expression classes are extended to support standard constructs like loops and assignments.
(You can ofcourse do some of that right now in 3.5, but there are alot more support for it in 4.0)
Roger Alsing
April 15, 2009 at 4:31 pm
Of course, you could use pass dynamic objects through a delegate and record what calls are made, and try to make some sense out of that. It works (I’ve done so). But it’s ugly.
Keith Farmer
February 3, 2010 at 9:17 pm
[...] and sort your list:myList.Sort(GetSortExpression());Some good discussions and samples on the topic:http://rogeralsing.com/2009/03/23/linq-expressions-from-and-to-delegates/Nate Kohari’s use in Community Server 5’s REST API: [...]
Pensieve: Building General Purpose Lambda Expressions
September 17, 2009 at 2:59 am
Quite useful!
Jack
September 27, 2009 at 6:26 am
Here is a quick thought:
Func methoddelegate = this.testmethod;
Expression action = () => methoddelegate(“1″, 2, new TestClass());
MethodCallExpression method = action.Body as MethodCallExpression;
based on what I know you can’t get an expression tree from a delegate because it isn’t an actual method call, it is just a definition. A similar situation would be to try and get the expression tree of an object, ex: Thread.
Brad Stitt
February 3, 2010 at 7:52 pm
Func<string, int, TestClass, int> methoddelegate = this.testmethod;
Expression<Action> action = () => methoddelegate(“1″, 2, new TestClass());
MethodCallExpression method = action.Body as MethodCallExpression;
reposted to fix invalid characters
Brad Stitt
February 3, 2010 at 7:54 pm
I use this for error logging which uses the logic previously posted. this creates a string representation of the method with parameter values.
example usage: ToString(() => somemethod(someparameter));
string ToString(Expression<Action> action)
{
MethodCallExpression call = action.Body as MethodCallExpression;
if (call == null) throw new ArgumentException();
StringBuilder message = new StringBuilder(call.Method.Name + “(“);
foreach (MemberExpression member in call.Arguments)
{
object paramvalue = (member.Expression as ConstantExpression).Value;
FieldInfo field = paramvalue.GetType().GetField(member.Member.Name);
object actualvalue = field.GetValue(paramvalue);
if (actualvalue is string)
{
actualvalue = “\”" + actualvalue + “\”";
}
message.Append(“(” + field.FieldType.ToString() + “) ” + field.Name + ” = ” + actualvalue.ToString() + “, “);
}
message.Remove(message.Length – 2, 2);
message.Append(“)”);
return message.ToString();
}
Brad Stitt
February 3, 2010 at 8:00 pm