示例#1
0
        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);
        }
示例#2
0
        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);
        }
示例#3
0
        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);
        }
示例#4
0
        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);
        }
示例#5
0
        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);
        }
示例#6
0
        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);
        }