C# 动态分配字段

C# 动态分配字段,c#,cil,reflection.emit,fieldinfo,C#,Cil,Reflection.emit,Fieldinfo,我正在尝试生成代码,以便将字段值动态分配给动态类。基本上,我最理想能做的就是做到这一点: il.Emit(操作码.Ldarg_0);//对象实例 il.Emit(操作码.Ldc_I4_0);//要分配给字段的值 il.Emit(操作码.Ld???,字段信息);//要将值分配给的FieldInfo il.Emit(操作码.Stfld);//某种类型的Stfld,弹出字段和值并赋值 我找不到任何适合我需要的指导。我的另一个想法是为每个字段生成一个setter方法并调用该方法,但我没有找到一个不将其

我正在尝试生成代码,以便将字段值动态分配给动态类。基本上,我最理想能做的就是做到这一点:

il.Emit(操作码.Ldarg_0);//对象实例
il.Emit(操作码.Ldc_I4_0);//要分配给字段的值
il.Emit(操作码.Ld???,字段信息);//要将值分配给的FieldInfo
il.Emit(操作码.Stfld);//某种类型的Stfld,弹出字段和值并赋值
我找不到任何适合我需要的指导。我的另一个想法是为每个字段生成一个setter方法并调用该方法,但我没有找到一个不将其转换为委托的方法,委托生成了大量样板代码

有谁有更好的解决方案吗

编辑: 问题是需要分配的字段必须在堆栈上找到,并且在分配时以某种方式弹出。不幸的是,没有一个CIL指令支持弹出一个fieldInfo来分配给它,但可能还有其他我没有想到的解决方案

EDIT2:我会再介绍一下周围的情况,希望上下文能让事情变得更清楚

我正在尝试将一种基于堆栈的vm字节码“重新编译”到CIL。所讨论的字节码不像CIL那样访问结构中的字段,即静态访问。相反,对要访问的字段的引用被推送到堆栈上,而
store
指令负责其余部分

下面是这个字节码的示例:

PushFloat 0.0
PushField [someField]
SetField

我希望获得的是类似于我上面编写的代码,但CIL只支持分配给在codegen时间已知的字段。

我使用
ldflda
stind
解决了这个问题:

il.Emit(操作码.Ldarg_0);//对象实例
il.Emit(操作码.Ldflda,字段信息);//将引用加载到字段
il.Emit(操作码转换);//转换为指针
il.Emit(操作码.Ldc_I4_0);//放在地里的东西
il.Emit(操作码.Stind_I4);//在字段中输入值

这似乎与我最初打算做的差不多。

您是否尝试过用C#编写您想要的代码,然后使用ILDasm对其进行反编译,看看编译器会生成什么?那么您到底需要什么?目前,无论出于何种原因,我们只看到一些不起作用的代码。但这不是这段代码实际应该做什么以及它应该做什么。@Sean我无法通过C#生成我需要的代码,但在CIL中有许多事情是C#无法生成的,所以我认为这不是问题的症结所在。我将编辑问题以添加一些信息。这不能用可验证的托管代码来完成,除非您想生成对
FieldInfo.SetValue
的调用(这并不比用C做得更好)。为托管对象设置字段并不是那么简单,这就是为什么没有通用的、简单的方法来间接地进行设置,除非您喜欢所描述的方法。我的建议是不要这样做,而是为特定字段生成特定代码,通过在一次调用中打包所有所需的setter来消除委托开销。即使最终得到一些有效的代码,请记住,与生成的静态字段分配相比,它的性能可能不太好,因为这样的练习基本上绕过了JIT本身可以做的任何优化(例如,可能会破坏内联),因此获得正确的细节(比如尊重
volatile
和对齐)也不是一件小事。有专门针对这一点的类型(如平面结构)更有意义;对于任意类型和字段,尝试这样做的可能性较小。结果可能是“太聪明了一半”,然后我所有关于“不可能”的评论都是错误的。很高兴知道,今天学到了一些东西:)