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