How to mutate a boxed struct using IL

后端 未结 5 1056
执笔经年
执笔经年 2020-12-24 07:41

Imagine we have a mutable struct (yes, don\'t start):

public struct MutableStruct
{
    public int Foo { get; set; }
    public override string          


        
5条回答
  •  庸人自扰
    2020-12-24 08:33

    Well, that was fun.

    Using Ldflda and Stind_* seems to work. Actually, it's mostly Unbox (see history for version that works with Ldflda and Stind_*).

    Here's what I hacked together in LinqPad to prove it out.

    public struct MutableStruct
    {
        public int Foo { get; set; }
    
        public override string ToString()
        {
            return Foo.ToString();
        }
    }
    
    void Main()
    {
        var foo = typeof(MutableStruct).GetProperty("Foo");
        var setFoo = foo.SetMethod;
    
        var dynMtd = new DynamicMethod("Evil", typeof(void), new [] { typeof(object), typeof(int) });
        var il = dynMtd.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);                       // object
        il.Emit(OpCodes.Unbox, typeof(MutableStruct));  // MutableStruct&
        il.Emit(OpCodes.Ldarg_1);                       // MutableStruct& int
        il.Emit(OpCodes.Call, setFoo);                  // --empty--
        il.Emit(OpCodes.Ret);                           // --empty--
    
        var del = (Action)dynMtd.CreateDelegate(typeof(Action));
    
        var mut = new MutableStruct { Foo = 123 };
    
        var boxed= (object)mut;
    
        del(boxed, 456);
    
        var unboxed = (MutableStruct)boxed;
        // unboxed.Foo = 456, mut.Foo = 123
    }
    

提交回复
热议问题