如何发出一个 System.Linq.Expression?

16
我有一些代码,使用System.Linq.Expressions和Expression.Lambda>.Compile()等方法生成各种Func<>委托。我想将生成的函数序列化成程序集以供后续使用。过去,我曾使用System.Reflection.Emit做过一些工作,但现在既然使用了Linq Expressions,我不想再走那条路了。
是否有机制可以序列化编译后的表达式或从Expressions命名空间到Emit命名空间的桥梁?
编辑
一些背景信息: 我正在开发一个查询引擎(主要是为了自己的学习和兴趣)。给定一个SQL语句,我想将其解析并转换为Lambda函数,然后将其序列化到磁盘上以供以后(和重复)执行。
在伪代码中,我已完成以下步骤:
Func<IEnumerable<T>, IEnumerable<T1>> query = Query.Parse<T, T1>("Select field AS A, field1 AS B from T where T.field2 > 5");

(其中,fieldfield1field2Type T的属性,ABType T1的属性。)我可以传递任何<T>的枚举到query中,并获得一个与查询条件匹配的<T1>的枚举结果。
因此,我想将query序列化到磁盘上作为已编译的程序集,以便在以后的某个时间加载它并评估不同的<T>集合而无需解析和编译它。我想象中的实现方式是:
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(...)
3个回答

4
LambdaExpression有一个CompileToMethod方法,它针对一个MethodBuilder。使用这个方法和Reflection.Emit,您应该能够创建一个类并将其写入程序集。

3

我不确定你的整体想法是什么,但是就纯粹看你的第二段,你可以编写基于表达式的代码,构建它,然后使用“Reflection.Emit”语言插件在Reflector中打开你的程序集。这个元-meta技巧将展示生成你的Expression/Lambda代码所需的反射.Emit语句。

-Oisin


我想我明白你的意思,但是如果你看一下我的编辑:在输入的运行时评估之前,我不知道表达式会是什么样子。 - dkackman

3
我认为没有办法做到这一点。毕竟,一个表达式可以捕获任意的运行时值,这些值无法序列化到程序集中。
似乎可以通过调用"expr.Compile().Method.GetMethodBody().GetILAsByteArray()"获取字节码IL,然后将其写入到MethodBuilder中,在程序集中进行写入。但不幸的是,这种方法行不通——GetMethodBody()调用失败,因为委托是动态的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接