如何在MSIL中返回struct对象?

时间:2015-09-30 03:08:18

标签: c# cil il

我想设置一个struct字段值并返回struct实例。 此代码在ClassType中工作,但在StructType上错误

[创建Setter]

    public static DynamicMemberSetter CreateFieldSetter(FieldInfo fieldInfo, Type declaringType = null)
    {
        if(declaringType == null) declaringType = fieldInfo.ReflectedType;
        var emit = new EmitHelper(Types.Object, DynamicSetMemberParams, declaringType);
        var isStatic = fieldInfo.IsStatic;
        if(!isStatic)
        {
            emit.DeclareLocal(declaringType);
            emit.ldarg_0
                .castType(declaringType)
                .stloc_0
                .ldloc_0
                .end();
        }
        var changeTypeMethod = typeof(Convert).GetMethod("ChangeType", new Type[] { Types.Object, Types.Type });
        var getTypeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle", new Type[] { typeof(RuntimeTypeHandle) });
        emit.ldarg_1
            .ldtoken(fieldInfo.FieldType)
            .call(getTypeFromHandleMethod)
            .call(changeTypeMethod)
            .castType(fieldInfo.FieldType)
            .end();


        emit.stfld(isStatic, fieldInfo)
            .end();

        if(isStatic)
        {
            emit.ldnull
                .end();
        }
        else
        {
            emit.ldloc_0
                .boxIfValueType(declaringType)
                .end();
        }

        emit.ret();
        return emit.CreateDelegate<DynamicMemberSetter>();
    }

[单元测试]

    [TestMethod()]
    public void CreateFieldSetterTest()
    {
        var m = new Fields.Model() { Public = "xs" };
        // Success
        Assert.AreEqual(m, DynamicFactory.CreateFieldSetter(Fields.Members.Public)(m, "a"));
        Assert.AreEqual(m, DynamicFactory.CreateFieldSetter(Fields.Members.Private)(m, "b"));
        Assert.AreEqual("a", m.Public);
        Assert.AreEqual("b", DynamicFactory.CreateFieldGetter(Fields.Members.Private)(m));


        var stm = new Fields.StructModel() { Field = "5" };
        var v = (Fields.StructModel)DynamicFactory.CreateFieldSetter(stm.GetType().GetField("Field"))(stm, "xx");
        //- Fail,the Field always "5" value. Why?! 
        Assert.AreEqual("xx", v.Field);
    }

我想达到这个效果,但我不知道如何实现,希望得到你的帮助。

0 个答案:

没有答案