Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I Emit a System.Linq.Expression?

I've got some code that generates various Func<> delegates using System.Linq.Expressions and Expression.Lambda<Func<>>.Compile() etc. I would like to be able to serialize the generated functions into an assembly for later use. In the past I've done some stuff with System.Reflection.Emit but now that Linq Expressions I'd rather not go that route again.

Is there a mechanism to serialize a compiled expression or some sort of bridge from the Expressions namespace to the Emit namespace?

Edit

Some background for context: I am working on a query engine (mostly for my own edification and enjoyment). Given a SQL statement I would like to parse and transform it into a lambda function and then serialize it to disk for later (and repeated execution).

In pseudo code I am to this point:

Func<IEnumerable<T>, IEnumerable<T1>> query = Query.Parse<T, T1>("Select field AS A, field1 AS B from T where T.field2 > 5");

(where field, field1 and field2 are properties of Type T and A and B are properties of Type T1. and I can pass any enumeration of <T> to query and get back and an enumeration of <T1> which matches the query criteria.

So I would like to serialize query to disk as an already compiled assembly so at a later date I can load it and evaluate different sets of <T> without parsing and compiling it. I am picturing something along the lines of:

AssemblyBuilder builder = new AssemblyBuilder(...);
ModuleBuilder module = builder.DefineDynamicModule(...);
TypeBuilder type = module.DefineType(...);
type.AddMethod(query);  // <--- where this piece does not exist as far as I know
builder.Emit(...)
like image 476
dkackman Avatar asked Feb 26 '10 22:02

dkackman


People also ask

What is System LINQ expression?

Expression Class (System.Linq.Expressions) Provides the base class from which the classes that represent expression tree nodes are derived. It also contains static (Shared in Visual Basic) factory methods to create the various node types. This is an abstract class.

What is expression tree in LINQ?

You can compile and run code represented by expression trees. This enables dynamic modification of executable code, the execution of LINQ queries in various databases, and the creation of dynamic queries. For more information about expression trees in LINQ, see How to use expression trees to build dynamic queries (C#).

What LINQ expressions are used to shape results in a query?

Q. What LINQ expressions are used to shape results in a query? When the linq query is executed, the select clause specifies the type of values that will be produced. By using group clause you can group your results based on a key that you specify.


3 Answers

LambdaExpression has a CompileToMethod method that targets a MethodBuilder. Using this and Reflection.Emit you should be able to create a class and write it to an assembly.

like image 108
N8allan Avatar answered Oct 14 '22 08:10

N8allan


I'm not sure what exactly your bigger picture is but looking purely at your second paragraph, you can write pure Expression based code, build it, and then open your assembly in Reflector using the "Reflection.Emit" language add-in. This piece of meta-meta trickery will show you the Reflection.Emit statements needed to generate your Expression/Lambda code dynamically.

-Oisin

like image 22
x0n Avatar answered Oct 14 '22 07:10

x0n


I don't think that there's any way to do this. After all, an Expression can capture arbitrary run time values, which couldn't be serialized into an assembly.

It would seem like you could get around this by calling expr.Compile().Method.GetMethodBody().GetILAsByteArray() to get the IL as bytes, which could then be written to a MethodBuilder in an assembly which you could then write to file. Unfortunately, this won't work - the GetMethodBody() call fails because the delegate is dynamic.

like image 29
kvb Avatar answered Oct 14 '22 06:10

kvb