我想设置一个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);
}
我想达到这个效果,但我不知道如何实现,希望得到你的帮助。