public static void EmitPackCode(Type type, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupPackMethod) { if (type.IsPrimitive || type.IsInterface) { throw new NotSupportedException(); } Variable arg_writer = Variable.CreateArg(0); Variable arg_obj = Variable.CreateArg(1); Variable local_i = Variable.CreateLocal(il.DeclareLocal(typeof(int))); if (!type.IsValueType) // null check { Label notNullLabel = il.DefineLabel(); il.EmitLd(arg_obj); il.Emit(OpCodes.Brtrue_S, notNullLabel); il.EmitLd(arg_writer); il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteNil", new Type[0])); il.Emit(OpCodes.Ret); il.MarkLabel(notNullLabel); } if (type.IsArray) { EmitPackArrayCode(mi, il, type, arg_writer, arg_obj, local_i, lookupPackMethod); goto FinallyProcess; } // MsgPackWriter.WriteMapHeader MemberInfo[] members = targetMemberSelector(type); il.EmitLd(arg_writer); il.EmitLdc(members.Length); il.Emit(OpCodes.Callvirt, typeof(MsgPackWriter).GetMethod("WriteMapHeader", new Type[] { typeof(int) })); for (int i = 0; i < members.Length; i++) { MemberInfo m = members[i]; Type mt = m.GetMemberType(); // write field-name il.EmitLd(arg_writer); il.EmitLdstr(memberNameFormatter(m)); il.EmitLd_True(); il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("Write", new Type[] { typeof(string), typeof(bool) })); // write value EmitPackMemberValueCode(mt, il, arg_writer, arg_obj, m, null, type, mi, lookupPackMethod); } FinallyProcess: il.Emit(OpCodes.Ret); }
private static void EmitUnpackArrayCode(Type arrayType, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupUnpackMethod) { Type elementType = arrayType.GetElementType(); MethodInfo method = typeof(PackILGenerator).GetMethod("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic); Variable variable = Variable.CreateArg(0); Variable variable2 = Variable.CreateLocal(il.DeclareLocal(arrayType)); Variable v = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable variable3 = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable v2 = Variable.CreateLocal(il.DeclareLocal(typeof(Type))); EmitUnpackReadAndTypeCheckCode(il, variable, typeof(MsgPackReader).GetMethod("IsArray"), method, nullCheckAndReturn: true); il.Emit(OpCodes.Ldtoken, elementType); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.EmitSt(v2); il.EmitLd(variable); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetProperty("Length").GetGetMethod()); il.EmitSt(v); il.EmitLd(v2); il.EmitLd(v); il.Emit(OpCodes.Call, typeof(Array).GetMethod("CreateInstance", new Type[2] { typeof(Type), typeof(int) })); il.Emit(OpCodes.Castclass, arrayType); il.EmitSt(variable2); MethodInfo meth = lookupUnpackMethod(elementType); Label label = il.DefineLabel(); Label label2 = il.DefineLabel(); il.EmitLdc(0); il.EmitSt(variable3); il.Emit(OpCodes.Br, label2); il.MarkLabel(label); il.EmitLd(variable2, variable3); il.EmitLd(variable); il.Emit(OpCodes.Call, meth); il.Emit(OpCodes.Stelem, elementType); il.EmitLd(variable3); il.EmitLdc(1); il.Emit(OpCodes.Add); il.EmitSt(variable3); il.MarkLabel(label2); il.EmitLd(variable3); il.EmitLd(v); il.Emit(OpCodes.Blt, label); il.EmitLd(variable2); il.Emit(OpCodes.Ret); }
public static void EmitPackCode(Type type, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupPackMethod) { if (type.IsPrimitive || type.IsInterface) { throw new NotSupportedException(); } Variable variable = Variable.CreateArg(0); Variable variable2 = Variable.CreateArg(1); Variable var_loop = Variable.CreateLocal(il.DeclareLocal(typeof(int))); if (!type.IsValueType) { Label label = il.DefineLabel(); il.EmitLd(variable2); il.Emit(OpCodes.Brtrue_S, label); il.EmitLd(variable); il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("WriteNil", new Type[0])); il.Emit(OpCodes.Ret); il.MarkLabel(label); } if (type.IsArray) { EmitPackArrayCode(mi, il, type, variable, variable2, var_loop, lookupPackMethod); } else { MemberInfo[] array = targetMemberSelector(type); il.EmitLd(variable); il.EmitLdc(array.Length); il.Emit(OpCodes.Callvirt, typeof(MsgPackWriter).GetMethod("WriteMapHeader", new Type[1] { typeof(int) })); foreach (MemberInfo memberInfo in array) { Type memberType = memberInfo.GetMemberType(); il.EmitLd(variable); il.EmitLdstr(memberNameFormatter(memberInfo)); il.EmitLd_True(); il.Emit(OpCodes.Call, typeof(MsgPackWriter).GetMethod("Write", new Type[2] { typeof(string), typeof(bool) })); EmitPackMemberValueCode(memberType, il, variable, variable2, memberInfo, null, type, mi, lookupPackMethod); } } il.Emit(OpCodes.Ret); }
static void EmitUnpackArrayCode(Type arrayType, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupUnpackMethod) { Type elementType = arrayType.GetElementType(); MethodInfo failedMethod = typeof(PackILGenerator).GetMethod("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic); Variable msgpackReader = Variable.CreateArg(0); Variable obj = Variable.CreateLocal(il.DeclareLocal(arrayType)); Variable num_of_elements = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable loop_idx = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable type = Variable.CreateLocal(il.DeclareLocal(typeof(Type))); // if (!MsgPackReader.Read() || !MsgPackReader.IsArray ()) UnpackFailed (); EmitUnpackReadAndTypeCheckCode(il, msgpackReader, typeof(MsgPackReader).GetMethod("IsArray"), failedMethod, true); // type = typeof (T) il.Emit(OpCodes.Ldtoken, elementType); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.EmitSt(type); // num_of_elements = (int)reader.Length il.EmitLd(msgpackReader); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetProperty("Length").GetGetMethod()); il.EmitSt(num_of_elements); // object o = Array.CreateInstance (Type, Length); il.EmitLd(type); il.EmitLd(num_of_elements); il.Emit(OpCodes.Call, typeof(Array).GetMethod("CreateInstance", new Type[] { typeof(Type), typeof(int) })); il.Emit(OpCodes.Castclass, arrayType); il.EmitSt(obj); // Unpack element method MethodInfo unpack_method = lookupUnpackMethod(elementType); // Loop labels Label lblLoopStart = il.DefineLabel(); Label lblLoopExpr = il.DefineLabel(); // i = 0; il.EmitLdc(0); il.EmitSt(loop_idx); il.Emit(OpCodes.Br, lblLoopExpr); il.MarkLabel(lblLoopStart); /* process */ il.EmitLd(obj, loop_idx); il.EmitLd(msgpackReader); il.Emit(OpCodes.Call, unpack_method); il.Emit(OpCodes.Stelem, elementType); // i ++ il.EmitLd(loop_idx); il.EmitLdc(1); il.Emit(OpCodes.Add); il.EmitSt(loop_idx); // i < num_of_fields; il.MarkLabel(lblLoopExpr); il.EmitLd(loop_idx); il.EmitLd(num_of_elements); il.Emit(OpCodes.Blt, lblLoopStart); // return il.EmitLd(obj); il.Emit(OpCodes.Ret); }
static void EmitUnpackMapCode(Type type, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupUnpackMethod, Func <Type, IDictionary <string, int> > lookupMemberMapping, MethodInfo lookupMemberMappingMethod) { MethodInfo failedMethod = typeof(PackILGenerator).GetMethod("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic); MemberInfo[] members = targetMemberSelector(type); IDictionary <string, int> member_mapping = lookupMemberMapping(type); for (int i = 0; i < members.Length; i++) { member_mapping.Add(memberNameFormatter(members[i]), i); } Variable msgpackReader = Variable.CreateArg(0); Variable obj = Variable.CreateLocal(il.DeclareLocal(type)); Variable num_of_fields = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable loop_idx = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable mapping = Variable.CreateLocal(il.DeclareLocal(typeof(IDictionary <string, int>))); Variable switch_idx = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable var_type = Variable.CreateLocal(il.DeclareLocal(typeof(Type))); // if (!MsgPackReader.Read()) UnpackFailed (); // if (MsgPackReader.Type == TypePrefixes.Nil) return null; // if (!MsgPackReader.IsMap ()) UnpackFailed (); EmitUnpackReadAndTypeCheckCode(il, msgpackReader, typeof(MsgPackReader).GetMethod("IsMap"), failedMethod, true); // type = typeof (T) il.Emit(OpCodes.Ldtoken, type); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.EmitSt(var_type); // mapping = LookupMemberMapping (typeof (T)) il.EmitLd(var_type); il.Emit(OpCodes.Call, lookupMemberMappingMethod); il.EmitSt(mapping); // object o = FormatterServices.GetUninitializedObject (Type); il.EmitLd(var_type); il.Emit(OpCodes.Call, typeof(FormatterServices).GetMethod("GetUninitializedObject")); il.Emit(OpCodes.Castclass, type); il.EmitSt(obj); // num_of_fields = (int)reader.Length il.EmitLd(msgpackReader); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetProperty("Length").GetGetMethod()); il.EmitSt(num_of_fields); // Loop labels Label lblLoopStart = il.DefineLabel(); Label lblLoopExpr = il.DefineLabel(); // i = 0; il.EmitLdc(0); il.EmitSt(loop_idx); il.Emit(OpCodes.Br, lblLoopExpr); il.MarkLabel(lblLoopStart); /* process */ // if (!MsgPackReader.Read() || !MsgPackReader.IsRaw()) UnpackFailed(); EmitUnpackReadAndTypeCheckCode(il, msgpackReader, typeof(MsgPackReader).GetMethod("IsRaw"), failedMethod, false); // MsgPackReader.ReadRawString () // if (!Dictionary.TryGetValue (,)) UnpackFailed(); Label lbl3 = il.DefineLabel(); il.EmitLd(mapping); il.EmitLd(msgpackReader); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetMethod("ReadRawString", new Type[0])); il.Emit(OpCodes.Ldloca_S, (byte)switch_idx.Index); il.Emit(OpCodes.Callvirt, typeof(IDictionary <string, int>).GetMethod("TryGetValue")); il.Emit(OpCodes.Brtrue, lbl3); il.Emit(OpCodes.Call, failedMethod); il.MarkLabel(lbl3); // switch Label[] switchCases = new Label[members.Length]; for (int i = 0; i < switchCases.Length; i++) { switchCases[i] = il.DefineLabel(); } Label switchCaseEndLabel = il.DefineLabel(); il.EmitLd(switch_idx); il.Emit(OpCodes.Switch, switchCases); il.Emit(OpCodes.Call, failedMethod); for (int i = 0; i < switchCases.Length; i++) { il.MarkLabel(switchCases[i]); MemberInfo minfo = members[i]; Type mt = minfo.GetMemberType(); MethodInfo unpack_method = lookupUnpackMethod(mt); il.EmitLd(obj); il.EmitLd(msgpackReader); il.Emit(OpCodes.Call, unpack_method); il.EmitStMember(minfo); il.Emit(OpCodes.Br, switchCaseEndLabel); } il.MarkLabel(switchCaseEndLabel); // i ++ il.EmitLd(loop_idx); il.EmitLdc(1); il.Emit(OpCodes.Add); il.EmitSt(loop_idx); // i < num_of_fields; il.MarkLabel(lblLoopExpr); il.EmitLd(loop_idx); il.EmitLd(num_of_fields); il.Emit(OpCodes.Blt, lblLoopStart); // return il.EmitLd(obj); il.Emit(OpCodes.Ret); }
private static void EmitUnpackMapCode(Type type, MethodInfo mi, ILGenerator il, Func <Type, MemberInfo[]> targetMemberSelector, Func <MemberInfo, string> memberNameFormatter, Func <Type, MethodInfo> lookupUnpackMethod, Func <Type, IDictionary <string, int> > lookupMemberMapping, MethodInfo lookupMemberMappingMethod) { MethodInfo method = typeof(PackILGenerator).GetMethod("UnpackFailed", BindingFlags.Static | BindingFlags.NonPublic); MemberInfo[] array = targetMemberSelector(type); IDictionary <string, int> dictionary = lookupMemberMapping(type); for (int i = 0; i < array.Length; i++) { dictionary.Add(memberNameFormatter(array[i]), i); } Variable variable = Variable.CreateArg(0); Variable v = Variable.CreateLocal(il.DeclareLocal(type)); Variable v2 = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable v3 = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable v4 = Variable.CreateLocal(il.DeclareLocal(typeof(IDictionary <string, int>))); Variable variable2 = Variable.CreateLocal(il.DeclareLocal(typeof(int))); Variable v5 = Variable.CreateLocal(il.DeclareLocal(typeof(Type))); EmitUnpackReadAndTypeCheckCode(il, variable, typeof(MsgPackReader).GetMethod("IsMap"), method, nullCheckAndReturn: true); il.Emit(OpCodes.Ldtoken, type); il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle")); il.EmitSt(v5); il.EmitLd(v5); il.Emit(OpCodes.Call, lookupMemberMappingMethod); il.EmitSt(v4); il.EmitLd(v5); il.Emit(OpCodes.Call, typeof(FormatterServices).GetMethod("GetUninitializedObject")); il.Emit(OpCodes.Castclass, type); il.EmitSt(v); il.EmitLd(variable); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetProperty("Length").GetGetMethod()); il.EmitSt(v2); Label label = il.DefineLabel(); Label label2 = il.DefineLabel(); il.EmitLdc(0); il.EmitSt(v3); il.Emit(OpCodes.Br, label2); il.MarkLabel(label); EmitUnpackReadAndTypeCheckCode(il, variable, typeof(MsgPackReader).GetMethod("IsRaw"), method, nullCheckAndReturn: false); Label label3 = il.DefineLabel(); il.EmitLd(v4); il.EmitLd(variable); il.Emit(OpCodes.Call, typeof(MsgPackReader).GetMethod("ReadRawString", new Type[0])); il.Emit(OpCodes.Ldloca_S, (byte)variable2.Index); il.Emit(OpCodes.Callvirt, typeof(IDictionary <string, int>).GetMethod("TryGetValue")); il.Emit(OpCodes.Brtrue, label3); il.Emit(OpCodes.Call, method); il.MarkLabel(label3); Label[] array2 = new Label[array.Length]; for (int j = 0; j < array2.Length; j++) { array2[j] = il.DefineLabel(); } Label label4 = il.DefineLabel(); il.EmitLd(variable2); il.Emit(OpCodes.Switch, array2); il.Emit(OpCodes.Call, method); for (int k = 0; k < array2.Length; k++) { il.MarkLabel(array2[k]); MemberInfo memberInfo = array[k]; Type memberType = memberInfo.GetMemberType(); MethodInfo meth = lookupUnpackMethod(memberType); il.EmitLd(v); il.EmitLd(variable); il.Emit(OpCodes.Call, meth); il.EmitStMember(memberInfo); il.Emit(OpCodes.Br, label4); } il.MarkLabel(label4); il.EmitLd(v3); il.EmitLdc(1); il.Emit(OpCodes.Add); il.EmitSt(v3); il.MarkLabel(label2); il.EmitLd(v3); il.EmitLd(v2); il.Emit(OpCodes.Blt, label); il.EmitLd(v); il.Emit(OpCodes.Ret); }