好吧,这个问题现在已经很老了,我正在等待tf get
完成......所以我会自己回答。
是的,LCG 在大多数情况下都死了。
我们过去经常使用 LCG,现在它已经全部转换为使用表达式树。它们更容易构建,代码更容易维护和调试,并且当您在开发过程中出错时,错误消息通常比“操作可能破坏运行时稳定”提供更多信息。
但是,也许最重要的是,表达式树是可以组合的,而 Reflection.Emit 不是。这意味着用于运行时代码生成的组件架构可以更加模块化,甚至允许插件扩展代码生成框架。
我发现 Reflection.Emit 支持但表达式树不直接支持的一件事是设置.initonly
字段。然而,这可以通过使用一个小助手类并在表达式树中调用它来实现,例如我使用的如下:
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;
}
}
值得一提的是,使用表达式树而不是 LCG 的一个缺点是表达式树的构建和编译肯定比直接发出原始操作码要慢。假设您正在缓存已编译的方法,这不太可能是一个重大问题,但这是仍然可能迫使您使用 LCG 的一个原因。