我如何发出System.Linq.Expression?

时间:2010-02-26 22:18:33

标签: c# .net-4.0 lambda reflection.emit linq-expressions

我有一些代码可以使用Func<>System.Linq.Expressions等生成各种Expression.Lambda<Func<>>.Compile()代理。我希望能够将生成的函数序列化到程序集中供以后使用。在过去,我已经使用System.Reflection.Emit做了一些事情,但是现在Linq表达式我宁愿不再去那条路了。

是否有机制将编译表达式或某种桥接从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");

(其中字段 field1 field2 Type T A的属性 B Type 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 个答案:

答案 0 :(得分:3)

我不确定你的大图是什么,但纯粹看你的第二段,你可以编写基于表达式的纯代码,构建它,然后使用“Reflection.Emit”语言添加 - 在Reflector中打开你的程序集 - 在。这段元元素技巧将向您展示动态生成Expression / Lambda代码所需的Reflection.Emit语句。

-Oisin

答案 1 :(得分:3)

我认为没有办法做到这一点。毕竟,Expression可以捕获任意运行时值,这些值无法序列化为程序集。

看起来您可以通过调用expr.Compile().Method.GetMethodBody().GetILAsByteArray()来获取IL作为字节,然后可以将其写入程序集中的MethodBuilder,然后您可以将其写入文件。不幸的是,这不起作用 - GetMethodBody()调用失败,因为委托是动态的。

答案 2 :(得分:3)

LambdaExpression有一个CompileToMethod方法,该方法以MethodBuilder为目标。使用this和Reflection.Emit,您应该能够创建一个类并将其写入程序集。