2010-02-26 3 views
16

Tengo un código que genera varios delegados Func<> utilizando System.Linq.Expressions y Expression.Lambda<Func<>>.Compile() etc. Me gustaría poder serializar las funciones generadas en un conjunto para su uso posterior. En el pasado he hecho algunas cosas con System.Reflection.Emit, pero ahora que Linq Expressions preferiría no seguir esa ruta de nuevo.¿Cómo emito un System.Linq.Expression?

¿Existe un mecanismo para serializar una expresión compilada o algún tipo de puente desde el espacio de nombres Expressions al espacio de nombres Emit?

Editar

Algunos antecedentes de contexto: estoy trabajando en un motor de consulta (en su mayoría para mi propia edificación y el disfrute). Dada una declaración SQL, me gustaría analizar y transformarla en una función lambda y luego serializarla en el disco para más adelante (y ejecución repetida).

En pseudocódigo Estoy a este punto:

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

(donde campo, campo1 y campo2 son propiedades de Tipo T y Un y B son propiedades de Tipo T1. y puedo pasar cualquier enumeración de <T> a query y obtener una enumeración de <T1> que coincida con los criterios de consulta.

Así que me gustaría serializar query en el disco como un ensamblado ya compilado, así que en una fecha posterior puedo cargarlo y evaluar diferentes conjuntos de <T> sin analizar y compilarlo. Estoy imaginando algo en la línea de:

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(...) 

Respuesta

3

No estoy seguro de qué es exactamente lo que su cuadro más grande es puramente pero mirando a su segundo párrafo, se puede escribir código basado Expresión pura, construirlo, y luego abrir su ensamblado en Reflector usando el complemento de lenguaje "Reflection.Emit". Esta pieza de trucos meta-meta le mostrará las instrucciones Reflection.Emit necesarias para generar su código Expression/Lambda de forma dinámica.

-Oisin

+0

Creo que veo lo que estás viendo pero si miras mi edición: No sé cómo serán las Expresiones hasta la evaluación del tiempo de ejecución de la entrada. – dkackman

3

No creo que hay alguna manera de hacer esto. Después de todo, un Expression puede capturar valores de tiempo de ejecución arbitrarios, que no se pudieron serializar en un ensamblaje.

Parecería que podría solucionar esto llamando al expr.Compile().Method.GetMethodBody().GetILAsByteArray() para obtener el IL como bytes, que luego podría escribirse en un MethodBuilder en un ensamblaje que luego podría escribir en el archivo. Lamentablemente, esto no funcionará: la llamada GetMethodBody() falla porque el delegado es dinámico.

3

LambdaExpression tiene un método CompileToMethod que se dirige a MethodBuilder. Usando esto y Reflection. Emit, deberías poder crear una clase y escribirla en un ensamble.

Cuestiones relacionadas