public override void EmitRead(Type type) { // arg0: stream, arg1: ctx LocalBuilder instance; if (type.IsValueType) instance = EmitNewInstance(type); else { var id = EmitHelper.EmitDeserializeRef(type); instance = EmitNewInstance(type); EmitHelper.EmitMarkRef(instance, id); } //var instance = <get instance>; //instance.OnDeserializing(); //<deserialize members if any> //instance.OnDeserialized(); //return instance; //var instance = <get instance>; var onDeserializing = type.GetMethodMarkedWith(typeof(OnDeserializingAttribute)); if (onDeserializing != null) { // instance.OnDeserializing(ctx) emit.ldloc_s(instance) .ldarg_1() .callvirt(onDeserializing); } Action<MetaMember, MethodInfo, bool> emitDeserializeMember = (member, deserialize, inheritance) => { // push stream and ctx and call Deserialize emit.ldarg_0() .ldarg_1() .call(deserialize); // cast if we went through base (which returns 'object') if (inheritance) emit.cast(member.Type); // store deserialize result in member member.emit_store(); }; var members = GetMembers(type); for (int i = 0; i < members.Length; i++) { var member = new MetaMember(members[i]); var inheritance = ctx.RequiresInheritance(member.Type); var deserialize = ctx.GetReadMethod(member.Type, inheritance); //<type|instance>.field|property = <cast if necessary>DeserializeT(stream, ctx); { if (member.IsStatic) { var SKIP = emit.deflabel(); Statics.HandleMark(1, SKIP); emitDeserializeMember(member, deserialize, inheritance); emit.mark(SKIP); } else { // push value if not static if (type.IsValueType) emit.ldloca_s(instance); else emit.ldloc_s(instance); emitDeserializeMember(member, deserialize, inheritance); } } } var onDeserialized = type.GetMethodMarkedWith(typeof(OnDeserializedAttribute)); if (onDeserialized != null) { // instance.OnDeserialized(ctx) emit.ldloc_s(instance) .ldarg_1() .callvirt(onDeserialized); } // return instance; emit.ret_s(instance); }
public override void EmitWrite(Type type) { // arg0: stream, arg1: value, arg2: ctx if (!type.IsValueType) EmitHelper.EmitSerializeRef(); var onSerializing = type.GetMethodMarkedWith(typeof(OnSerializingAttribute)); if (onSerializing != null) { // value.OnSerializing(ctx) emit.ldarg_1() .ldarg_2() .callvirt(onSerializing); } var members = GetMembers(type); for (int i = 0; i < members.Length; i++) { var member = new MetaMember(members[i]); var memberType = member.Type; // Serialize(stream, <type|value>.member, ctx) { if (member.IsStatic) { var SKIP = emit.deflabel(); Statics.HandleMark(2, SKIP); // push stream emit.ldarg_0(); // push member member.emit_load(); // push ctx and call serialize var serialize = ctx.GetWriteMethod(memberType); emit.ldarg_2() .call(serialize); emit.mark(SKIP); } else { // push stream emit.ldarg_0(); // push value if member is not static if (type.IsValueType) emit.ldarga_s(1); else emit.ldarg_s(1); // push member member.emit_load(); // push ctx and call serialize var serialize = ctx.GetWriteMethod(memberType); emit.ldarg_2() .call(serialize); } } } var onSerialized = type.GetMethodMarkedWith(typeof(OnSerializedAttribute)); if (onSerialized != null) { // value.OnSerialized(ctx) emit.ldarg_1() .ldarg_2() .callvirt(onSerialized); } emit.ret(); }