C# Reflection - 如何为结构设置字段值

标签 c# reflection struct reflection.emit

如何使用 DynamicMethod 通过反射将值设置到结构字段 - myStruct.myField 中?当我调用 setter(myStruct, 111) 时,值没有设置,因为 MyStruct 是值类型。 Console.WriteLine(myStruct.myField) 显示值 3。
如何修改GetDelegate方法将值赋给myStruct.myField

public struct MyStruct
{
    public int myField;
}

public delegate void SetHandler(object source, object value);

private static SetHandler GetDelegate(Type type, FieldInfo fieldInfo)
{
    DynamicMethod dm = new DynamicMethod("setter", typeof(void), new Type[] { typeof(object), typeof(object) }, type, true);
    ILGenerator setGenerator = dm.GetILGenerator();

    setGenerator.Emit(OpCodes.Ldarg_0);
    setGenerator.DeclareLocal(type);
    setGenerator.Emit(OpCodes.Unbox_Any, type);
    setGenerator.Emit(OpCodes.Stloc_0);
    setGenerator.Emit(OpCodes.Ldloca_S, 0);
    setGenerator.Emit(OpCodes.Ldarg_1);
    setGenerator.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
    setGenerator.Emit(OpCodes.Stfld, fieldInfo);
    setGenerator.Emit(OpCodes.Ldloc, 0);
    setGenerator.Emit(OpCodes.Box, type);
    setGenerator.Emit(OpCodes.Ret);
    return (SetHandler)dm.CreateDelegate(typeof(SetHandler));
}

MyStruct myStruct = new MyStruct();
myStruct.myField = 3;

FieldInfo fi = typeof(MyStruct).GetField("myField", BindingFlags.Public | BindingFlags.Instance);

SetHandler setter = GetDelegate(typeof(MyStruct), fi);
setter(myStruct, 111);
Console.WriteLine(myStruct.myField);

最佳答案

编辑:I made this mistake again - 有趣的事实; unbox-any 返回; unbox 返回指向数据的指针 - 这允许就地变异。

这是工作的 IL 生成:

    setGenerator.Emit(OpCodes.Ldarg_0);
    setGenerator.Emit(OpCodes.Unbox, type);
    setGenerator.Emit(OpCodes.Ldarg_1);
    setGenerator.Emit(OpCodes.Unbox_Any, fieldInfo.FieldType);
    setGenerator.Emit(OpCodes.Stfld, fieldInfo);
    setGenerator.Emit(OpCodes.Ret);

但是!这是在改变盒装副本;之后您需要拆箱:

    object obj = myStruct;
    setter(obj, 111);
    MyStruct andBackAgain = (MyStruct)obj;
    Console.WriteLine(andBackAgain.myField);
    Console.WriteLine(myStruct.myField);

要就地执行此操作,您可能需要该方法采用 ref MyStruct,或返回 MyStruct。您可以退回盒装副本,但这并不能使它更易于使用。坦率地说,这是没有实际意义的:结构通常不应该是可变的。

关于C# Reflection - 如何为结构设置字段值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25631322/

相关文章:

C# 和甲骨文 : Output parameter is getting truncated

java - 如何动态创建实现某些接口(interface)的新类并实例化它?

c# - 使用具有 "params"参数的反射调用函数 (MethodBase)

c# - .NET 反射 : how to get properties defined on partial class

c - C 中另一个结构体内部的结构体

c# - C# Windows Phone XNA 应用程序中的可选参数

c# - 序列化或反序列化 JSON 期间的 ASP.NET MVC4 错误 - 大数据

c - 通过初始化程序设置结构数组元素的语法?

c - 指向结构内部结构的双指针

c# - 机器人框架 V4 : Reset Bot in Messenger