0

I want to set a struct field value and return the struct instance. This code working in ClassType, but error on StructType.

[Create 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>();
    }

[Unit Test]

    [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);
    }

I want to achieve this effect, but I do not know how to achieve, hoping to get your help.

Treenew
  • 1
  • 1
  • 2
    I suggest to write a sample program where you create a `struct` with a field and set this field. Then take a look at the generated IL and try to compare with the code you have writen. I am pretty sure you find the difference. – ckruczek Sep 30 '15 at 04:42
  • Why emit.ldloc_0.ret().end(); is 5 value?? – Treenew Sep 30 '15 at 05:01
  • My quick guess is that you are passing the structure as a copy. I suggest trying to change the parameter of the delegate to `ref StructType`. – IS4 Nov 13 '15 at 19:55

0 Answers0