private static SerializationFactory CreateFactory(Type t) { var fields = DeepEquality.GetAllFields(t) //.OrderBy(fi => (int)fi.GetManagedOffset()) // [StructLayout.Sequential] doesn't work with this .OrderBy(fi => (int)Marshal.OffsetOf(t, fi.Name)) .ToList(); var rmeth = new DynamicMethod(t.Name + "_r", null, new[] { typeof(object), typeof(BinaryReader) }, true); var wmeth = new DynamicMethod(t.Name + "_w", null, new[] { typeof(object), typeof(BinaryWriter) }, true); { var il = rmeth.GetILGenerator(); var target = il.DeclareLocal(t); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, t); il.Emit(OpCodes.Stloc, target); foreach (var field in fields) { il.Emit(OpCodes.Ldloc, target); il.Emit(OpCodes.Ldarg_1); MethodInfo m; if (!readhandlers.TryGetValue(field.FieldType, out m)) { throw new InvalidOperationException("(R) Can't handle nested type " + field.FieldType); } il.Emit(OpCodes.Callvirt, m); il.Emit(OpCodes.Stfld, field); } il.Emit(OpCodes.Ret); } { var il = wmeth.GetILGenerator(); var target = il.DeclareLocal(t); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, t); il.Emit(OpCodes.Stloc, target); foreach (var field in fields) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldloc, target); il.Emit(OpCodes.Ldfld, field); MethodInfo m; if (!writehandlers.TryGetValue(field.FieldType, out m)) { throw new InvalidOperationException("(W) Can't handle nested type " + field.FieldType); } il.Emit(OpCodes.Callvirt, m); } il.Emit(OpCodes.Ret); } return(new SerializationFactory { Type = t, Read = (Reader)rmeth.CreateDelegate(typeof(Reader)), Write = (Writer)wmeth.CreateDelegate(typeof(Writer)) }); }