.net 4.0 轻量级代码生成(LCG)死了吗?

.net 4.0 轻量级代码生成(LCG)死了吗?,.net-4.0,code-generation,lcg,.net 4.0,Code Generation,Lcg,在.NET2.0-3.5框架中,LCG(也称为DynamicMethod类)是一种在运行时发出轻量级方法的好方法,而不需要类结构来支持它们 在.NET 4.0中,表达式树现在支持语句和块,因此似乎提供了足够的功能来构建这种方法可能需要的任何功能,并且可以以比直接发出CIL操作代码更简单、更安全的方式构建。(这句话来源于今天将一些最复杂的LCG代码转换为使用表达式树构建和编译的实验。) 那么,有没有理由在任何新代码中使用LCG呢?有什么是表达式树不能做的吗?或者它现在是一个“死”功能吗?这个问题现

在.NET2.0-3.5框架中,LCG(也称为DynamicMethod类)是一种在运行时发出轻量级方法的好方法,而不需要类结构来支持它们

在.NET 4.0中,表达式树现在支持语句和块,因此似乎提供了足够的功能来构建这种方法可能需要的任何功能,并且可以以比直接发出CIL操作代码更简单、更安全的方式构建。(这句话来源于今天将一些最复杂的LCG代码转换为使用表达式树构建和编译的实验。)


那么,有没有理由在任何新代码中使用LCG呢?有什么是表达式树不能做的吗?或者它现在是一个“死”功能吗?

这个问题现在已经很老了,我正在等待
tf get
完成。。。所以我自己来回答

是的,LCG在大多数情况下是死的

我们过去经常使用LCG,现在已经全部转换为使用表达式树。它们更易于构建,代码更易于维护和调试,并且当您在开发过程中出错时,错误消息通常比“操作可能会破坏运行时稳定”更具信息性

但是,也许最重要的是,表达式树的可组合性与Reflection.Emit不同。这意味着用于运行时代码生成的组件的体系结构可以更加模块化,甚至允许插件扩展代码生成框架

我发现在表达式树中不直接支持的反射.Emit支持的一件事是设置
.initonly
字段。然而,这可以通过使用一个小的helper类并在表达式树中调用它来实现,例如,我使用的一个如下所示:

internal static class FieldHelper
{
    public static TTarget AssignInitOnlyField<TTarget, TField>(
        TTarget target, string fieldName, TField value)
    {
        var field = target.GetType().GetField(
            fieldName, 
            BindingFlags.Instance|BindingFlags.Public|BindingFlags.NonPublic);
        var boxed = (object)target; // required for value type support
        field.SetValue(boxed, value);
        return (TTarget)boxed;
    }
}
内部静态类FieldHelper
{
公共静态TTarget AssignInitOnlyField(
t目标,字符串字段名,TField值)
{
var field=target.GetType().GetField(
字段名,
BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var boxed=(object)target;//需要值类型支持
字段。设置值(已装箱,值);
返回(t目标)装箱;
}
}

值得一提的是,使用表达式树而不是LCG的一个缺点是,表达式树的构造和编译肯定比直接发出原始操作代码慢。假设您正在缓存已编译的方法,这不太可能是一个重大问题,但这是仍然可能迫使您使用LCG的一个原因。

没有任何中间步骤,直接构建CIL是没有意义的。但是,使用您自己的最终目标是IL的中间语言是非常好的。表达式树等是不够的——它只是一种语言,而在实现DSL时,您需要许多不同的语义


你可以轻易地发出不安全的代码(有很多LDFTN等),你可以发出尾部调用(不确定表达式是否可行),对虚拟方法的非虚拟调用,你可以有效地构造带有标签和跳转的大型状态自动机,等。表达式树是如此有限,以至于我无法理解如何将它们与原始CIL进行比较。

LCG指的是超出范围后可以收集的方法。LINQ表达式使用LCG或法线反射发射。。。所以LCG肯定没有死。此外,LINQ表达式并不支持ref参数、ldtoken、实例方法、属性等所有内容。对于大多数运行时生成的代码来说,表达式树无疑是一种方法。但是,您应该清楚地认识到,它是有限的,不能让您访问MSIL语言的全部功能。因此,LGC和ILGenerator肯定会留下来完成要求更高的任务。

答案显然是否定的。LCG非常有用,因为它允许在运行时编译IL,使其性能更高。如果您不需要快速生成代码,那么就不需要它。所以基本上他们LCG仍然有它的利基。