Func <BasePackable, Type, Stream, object> GetReadFunc(Type type) { if (ReadFuncs.ContainsKey(type)) { return(ReadFuncs[type]); } foreach (var t in type.GetInterfaces()) { if (UnpackInterfaces.ContainsKey(t)) { return(UnpackInterfaces[t]); } } throw new NotSupportedException(); }
public Action <object, Stream> CreateRead(Type type) { var members = GetMembers(type); var ret = new DynamicMethod("Read_" + type.MetadataToken, null, new Type[] { typeof(object), typeof(Stream) }); var il = ret.GetILGenerator(); foreach (MemberInfo m in members) { var f = m as FieldInfo; var p = m as PropertyInfo; Type mtype = null; if (m is FieldInfo) { mtype = f.FieldType; } else if (m is PropertyInfo) { mtype = p.PropertyType; } if (!ReadFuncs.ContainsKey(mtype)) { throw new NotSupportedException(); } var ifnotnull = il.DefineLabel(); var ifnull = il.DefineLabel(); if (!mtype.IsValueType) { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, ReadFuncs[typeof(byte)].Method); il.Emit(OpCodes.Unbox_Any, typeof(byte)); il.Emit(OpCodes.Brtrue, ifnotnull); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, type); il.Emit(OpCodes.Ldnull); if (m is FieldInfo) { il.Emit(OpCodes.Stfld, f); } else if (m is PropertyInfo) { il.Emit(OpCodes.Call, p.GetSetMethod()); } il.Emit(OpCodes.Br, ifnull); } il.MarkLabel(ifnotnull); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, type); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Call, ReadFuncs[mtype].Method); if (mtype.IsValueType) { il.Emit(OpCodes.Unbox_Any, mtype); } else { il.Emit(OpCodes.Castclass, mtype); } if (m is FieldInfo) { il.Emit(OpCodes.Stfld, f); } else if (m is PropertyInfo) { il.Emit(OpCodes.Call, p.GetSetMethod()); } il.MarkLabel(ifnull); } il.Emit(OpCodes.Ret); return((Action <object, Stream>)ret.CreateDelegate(typeof(Action <object, Stream>))); }