c# - ¿Cómo emito un System.Linq.Expression?
if lambda c# (3)
LambdaExpression tiene un método CompileToMethod que se dirige a un MethodBuilder. Usando esto y Reflection.Emit deberías poder crear una clase y escribirla en un ensamblaje.
Tengo un código que genera varios delegados de Func<>
usando System.Linq.Expressions
y Expression.Lambda<Func<>>.Compile()
etc. Me gustaría poder serializar las funciones generadas en un ensamblaje para más adelante utilizar. En el pasado he hecho algunas cosas con System.Reflection.Emitir, pero ahora que Linq Expressions prefiero no volver a tomar esa ruta.
¿Existe un mecanismo para serializar una expresión compilada o algún tipo de puente desde el espacio de nombres de Expressions
espacio de nombres Emit
?
Editar
Algunos antecedentes para el contexto: estoy trabajando en un motor de consulta (principalmente para mi propia edificación y disfrute). Dada una sentencia de SQL, me gustaría analizarla y transformarla en una función lambda y luego serializarla en el disco para más tarde (y repetir la ejecución).
En pseudo có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 field , field1 y field2 son propiedades de Tipo T y A y B son propiedades de Tipo T1 . Puedo pasar cualquier enumeración de <T>
para query
y recuperar y una enumeración de <T1>
que coincida con los criterios de consulta.
Así que me gustaría serializar la query
en el disco como un ensamblaje ya compilado para que en una fecha posterior pueda cargarlo y evaluar diferentes conjuntos de <T>
sin analizarlo ni compilarlo. Me estoy imaginando algo como:
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(...)
No creo que haya ninguna manera de hacer esto. Después de todo, una Expression
puede capturar valores de tiempo de ejecución arbitrarios, que no se pueden serializar en un ensamblaje.
Parecería que podrías evitar esto llamando a expr.Compile().Method.GetMethodBody().GetILAsByteArray()
para obtener el IL como bytes, que luego podrían escribirse en un MethodBuilder
en un ensamblaje al que luego podrías escribir expediente. Desafortunadamente, esto no funcionará, la llamada GetMethodBody()
falla porque el delegado es dinámico.
No estoy seguro de cuál es exactamente su imagen más grande, pero al mirar puramente su segundo párrafo, puede escribir código basado en Expression puro, construirlo y luego abrir su ensamblaje en Reflector usando el complemento de lenguaje "Reflection.Emit". Este truco de meta-meta te mostrará las declaraciones de Reflection.Emit necesarias para generar tu código de Expresión / Lambda dinámicamente.
-Oisin