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>, IEnume开发者_运维知识库rable<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(...)
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.
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
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.
精彩评论