예제 #1
0
        private static Action <object, object> BuildFoister(FieldInfo field)
        {
            var methodName = "FieldFoister$";

            if (field.IsStatic)
            {
                methodName += field.DeclaringType + "$";
            }
            methodName += field.Name + "$" + Guid.NewGuid();
            var dynamicMethod = new DynamicMethod(methodName, typeof(void), new[] { typeof(object), typeof(object) }, typeof(FieldsExtractor), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                if (!field.IsStatic)
                {
                    il.Ldarg(0);
                    il.Castclass(field.DeclaringType);
                }
                il.Ldarg(1);
                if (field.FieldType.IsValueType)
                {
                    il.Unbox_Any(field.FieldType);
                }
                else
                {
                    il.Castclass(field.FieldType);
                }
                il.Stfld(field);
                il.Ret();
            }
            return((Action <object, object>)dynamicMethod.CreateDelegate(typeof(Action <object, object>)));
        }
예제 #2
0
        private static Func <object, object, int> EmitCompareDelegate()
        {
            var method          = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(object) }, typeof(string), true);
            var xsdDateTimeType = typeof(XmlReader).Assembly.GetTypes().FirstOrDefault(type => type.Name == "XsdDateTime");

            if (xsdDateTimeType == null)
            {
                throw new InvalidOperationException("The type 'XsdDateTime' is not found");
            }
            var compareMethod = xsdDateTimeType.GetMethod("Compare", BindingFlags.Static | BindingFlags.Public);

            if (compareMethod == null)
            {
                throw new InvalidOperationException("The method 'XsdDateTime.Compare' is not found");
            }
            using (var il = new GroboIL(method))
            {
                var strongBoxType = typeof(StrongBox <>).MakeGenericType(xsdDateTimeType);
                var valueField    = strongBoxType.GetField("Value", BindingFlags.Instance | BindingFlags.Public);
                il.Ldarg(0);                 // stack: [arg0]
                il.Castclass(strongBoxType); // stack: [(StrongBox<XsdDateTime>)arg0]
                il.Ldfld(valueField);        // stack: [((StrongBox<XsdDateTime>)arg0).Value]
                il.Ldarg(1);                 // stack: [((StrongBox<XsdDateTime>)arg0).Value, arg1]
                il.Castclass(strongBoxType); // stack: [((StrongBox<XsdDateTime>)arg0).Value, (StrongBox<XsdDateTime>)arg1]
                il.Ldfld(valueField);        // stack: [((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value]
                il.Call(compareMethod);      // stack: [XsdDateTime.CompareTo(((StrongBox<XsdDateTime>)arg0).Value, ((StrongBox<XsdDateTime>)arg1).Value)]
                il.Ret();
            }
            return((Func <object, object, int>)method.CreateDelegate(typeof(Func <object, object, int>)));
        }
예제 #3
0
        private static Func <object, MethodBase, SignatureHelper, uint> BuildGetTokenFor()
        {
            var parameterTypes = new[] { typeof(object), typeof(MethodBase), typeof(SignatureHelper) };
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(uint), parameterTypes, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);                         // stack: [scope]
                il.Castclass(dynamicScopeType);
                il.Ldarg(1);                         // stack: [scope, method]
                il.Castclass(runtimeMethodInfoType); // stack: [scope, (RuntimeMethodInfo)method]
                il.Ldarg(2);                         // stack: [scope, (RuntimeMethodInfo)method, signature]

                var constructor = varArgsMethodType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { runtimeMethodInfoType, typeof(SignatureHelper) }, null);
                if (constructor == null)
                {
                    throw new MissingMethodException("VarArgsMethod", ".ctor");
                }
                var getTokenForMethod = dynamicScopeType.GetMethod("GetTokenFor", BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { varArgsMethodType }, null);
                if (getTokenForMethod == null)
                {
                    throw new MissingMethodException("DynamicScope", "GetTokenFor");
                }

                il.Newobj(constructor);     // stack: [scope, new VarArgsMethod((RuntimeMethodInfo)method, signature)]
                il.Call(getTokenForMethod); // stack: [scope.GetTokenFor(new VarArgsMethod((RuntimeMethodInfo)method, signature))]

                il.Ret();
            }

            return((Func <object, MethodBase, SignatureHelper, uint>)method.CreateDelegate(typeof(Func <object, MethodBase, SignatureHelper, uint>)));
        }
예제 #4
0
        private WriterDelegate BuildWriter(Type type, bool ignoreCustomSerialization)
        {
            IntPtr writer = GetWriter(type, ignoreCustomSerialization);

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), new[] { typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }, module, true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type);                                                                                                                                // stack: [(type)obj]
                }
                il.Ldarg(1);                                                                                                                                           // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);                                                                                                                                           // stack: [(type)obj, writeEmpty, result]
                il.Ldarg(3);                                                                                                                                           // stack: [(type)obj, writeEmpty, result, ref index]
                il.Ldarg(4);                                                                                                                                           // stack: [(type)obj, writeEmpty, result, ref index, context]
                il.Ldc_IntPtr(writer);
                il.Calli(CallingConventions.Standard, typeof(void), new[] { type, typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext) }); // writer.write<T>((type)obj, writeEmpty, result, ref index, context); stack: []
                il.Ret();
            }

            return((WriterDelegate)dynamicMethod.CreateDelegate(typeof(WriterDelegate)));
        }
예제 #5
0
        private static KeyValuePair <Delegate, IntPtr> GetReader(ReaderMethodBuilderContext context, Type type)
        {
            var method = new DynamicMethod("Read_" + type.Name + "_AndCastToObject_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), typeof(object).MakeByRefType(), typeof(ReaderContext)
            }, context.Context.Module, true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(2);      // stack: [ref result]
                il.Ldarg(0);      // stack: [ref result, data]
                il.Ldarg(1);      // stack: [ref result, data, ref index]
                var value = il.DeclareLocal(type);
                il.Ldloca(value); // stack: [ref result, data, ref index, ref value]
                il.Ldarg(3);      // stack: [ref result, data, ref index, ref value, context]

                ReaderMethodBuilderContext.CallReader(il, type, context.Context);

                il.Ldloc(value); // stack: [ref result, value]
                if (type.IsValueType)
                {
                    il.Box(type); // stack: [ref result, (object)value]
                }
                else
                {
                    il.Castclass(type);
                }
                il.Stind(typeof(object)); // result = (object)value
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
예제 #6
0
        private static KeyValuePair <Delegate, IntPtr> GetWriter(WriterMethodBuilderContext context, Type type)
        {
            var method = new DynamicMethod("CastTo_" + type.Name + "_AndWrite_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(object), typeof(bool), typeof(IntPtr), typeof(int).MakeByRefType(), typeof(WriterContext)
            }, context.Context.Module, true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type); // stack: [(type)obj]
                }
                il.Ldarg(1);            // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);            // stack: [(type)obj, writeEmpty, result]
                il.Ldarg(3);            // stack: [(type)obj, writeEmpty, result, ref index]
                il.Ldarg(4);            // stack: [(type)obj, writeEmpty, result, ref index, context]
                context.CallWriter(il, type);
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(WriterDelegate <object>));

            return(new KeyValuePair <Delegate, IntPtr>(@delegate, GroBufHelpers.ExtractDynamicMethodPointer(method)));
        }
예제 #7
0
        public static Func <Dictionary <string, object>, object> GenerateMethod(Type type)
        {
            var da = AppDomain.CurrentDomain.DefineDynamicAssembly(
                new AssemblyName("dyn"),                 // call it whatever you want
                AssemblyBuilderAccess.RunAndSave);

            var dm = da.DefineDynamicModule("dyn_mod", "dyn.dll");
            var dt = dm.DefineType("dyn_type");



            var emiter = Emit <Func <int> > .NewDynamicMethod("MyMethod");

            var method = dt.DefineMethod(
                "Foo",
                MethodAttributes.Public | MethodAttributes.Static, typeof(object),
                new[] { typeof(Dictionary <string, object>) });

            method.DefineParameter(1, ParameterAttributes.None, "dictionary");


            using (var il = new GroboIL(method))
            {
                var target = il.DeclareLocal(type);
                var value  = il.DeclareLocal(typeof(object));

                il.Newobj(type.GetConstructor(Type.EmptyTypes)); // [Person]
                il.Stloc(target);                                // []
                foreach (var property in type.GetProperties())
                {
                    var label = il.DefineLabel("ifLabel");

                    il.Ldarg(0);                          // [Dictionary<String, Object>]
                    il.Ldstr(property.Name);              // [Dictionary<String, Object>, String]
                    il.Ldloca(value);                     // [Dictionary<String, Object>, String, Object&]
                    il.Call(typeof(Dictionary <string, object>)
                            .GetMethod("TryGetValue"));   // [Boolean]

                    il.Brfalse(label);                    // []

                    il.Ldloc(target);                     // [Person]
                    il.Ldloc(value);                      // [Person, Object]
                    il.Castclass(typeof(string));         // [Dictionary<String, Object>, String]
                    il.Call(property.GetSetMethod(true)); // []

                    il.MarkLabel(label);
                }

                il.Ldloc(target);
                il.Ret();
                Console.WriteLine(il.GetILCode());
            }


            dt.CreateType();
            da.Save("dyn.dll");


            return((dic) => dt.GetMethod("Foo").Invoke(null, new object[] { dic }));
        }
예제 #8
0
        private SizeCounterDelegate BuildCounter(Type type, bool ignoreCustomSerialization)
        {
            IntPtr counter = GetCounter(type, ignoreCustomSerialization);

            var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(int), new[] { typeof(object), typeof(bool), typeof(WriterContext) }, GetType(), true);

            using (var il = new GroboIL(dynamicMethod))
            {
                il.Ldarg(0); // stack: [obj]
                if (type.IsValueType)
                {
                    il.Unbox_Any(type); // stack: [(type)obj]
                }
                else
                {
                    il.Castclass(type);                                                                                  // stack: [(type)obj]
                }
                il.Ldarg(1);                                                                                             // stack: [(type)obj, writeEmpty]
                il.Ldarg(2);                                                                                             // stack: [(type)obj, writeEmpty, context]
                il.Ldc_IntPtr(counter);                                                                                  // stack: [(type)obj, writeEmpty, context, counter]
                il.Calli(CallingConventions.Standard, typeof(int), new[] { type, typeof(bool), typeof(WriterContext) }); // counter((type)obj, writeEmpty, context); stack: []
                il.Ret();
            }

            return((SizeCounterDelegate)dynamicMethod.CreateDelegate(typeof(SizeCounterDelegate)));
        }
예제 #9
0
            private static Func <Type, bool> BuildIsATypeBuilderInstantiationChecker()
            {
                var dynamicMethod = new DynamicMethod(Guid.NewGuid().ToString(), typeof(bool), new[] { typeof(Type) }, typeof(ReflectionExtensions), true);

                using (var il = new GroboIL(dynamicMethod))
                {
                    il.Ldarg(0);
                    il.Castclass(typeBuilderInstantiationType);
                    il.Ldnull();
                    il.Cgt(true);
                    il.Ret();
                }
                return((Func <Type, bool>)dynamicMethod.CreateDelegate(typeof(Func <Type, bool>)));
            }
예제 #10
0
        public void GetReadILCode(PropertyData prop, BinaryStruct currentStruct, GroboIL il, GroboIL.Local binaryStruct, GroboIL.Local buffer, GroboIL.Local result, GroboIL.Local typeSize, GroboIL.Local offset, bool listValue)
        {
            var exitLabel = il.DefineLabel("exit");

            BinaryStruct.ReadObjectNull(il, exitLabel, buffer, offset, typeSize);
            var len = il.DeclareLocal(typeof(int));

            il.Ldloc(buffer);
            il.Ldloc(offset);
            il.Call(readBitConverterMethodInfo);
            il.Stloc(len);

            BinaryStruct.WriteOffsetAppend(il, offset, 4);

            if (!listValue)
            {
                il.Ldloc(result);
                il.Ldarg(1);
            }
            else
            {
                il.Ldloc(binaryStruct);
            }
            il.Call(codingMethodInfo);

            il.Castclass(typeof(UTF8Encoding));

            il.Ldloc(buffer);
            il.Ldloc(offset);
            il.Ldloc(len);

            il.Call(currentStruct.Coding.GetType().GetMethod("GetString", new Type[] { typeof(byte[]), typeof(int), typeof(int) }), isVirtual: true);

            if (!listValue)
            {
                il.Call(prop.Setter);
            }
            else
            {
                il.Stloc(result);
            }

            BinaryStruct.WriteOffsetAppend(il, offset, len);
            il.MarkLabel(exitLabel);
        }
예제 #11
0
        private static void BuildFactoryByDynamicILGenerator()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(ILGenerator) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Castclass(dynamicILGeneratorType);
                var constructor = dynamicResolverType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { dynamicILGeneratorType }, null);
                if (constructor == null)
                {
                    throw new MissingMethodException("DynamicResolver", ".ctor");
                }
                il.Newobj(constructor);
                il.Ret();
            }

            factoryByDynamicILGenerator = (Func <ILGenerator, object>)method.CreateDelegate(typeof(Func <ILGenerator, object>));
        }
예제 #12
0
        private static void BuildGetRawEHInfoDelegate()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(byte[]), new[] { typeof(object) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Castclass(dynamicResolverType);
                var getRawEHInfoMethod = dynamicResolverType.GetMethod("GetRawEHInfo", BindingFlags.Instance | BindingFlags.NonPublic);
                if (getRawEHInfoMethod == null)
                {
                    throw new MissingMethodException("DynamicResolver", "GetRawEHInfo");
                }
                il.Call(getRawEHInfoMethod);
                il.Ret();
            }

            getRawEHInfoDelegate = (Func <object, byte[]>)method.CreateDelegate(typeof(Func <object, byte[]>));
        }
예제 #13
0
        private static Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo> BuildGetDynamicILInfo()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(GrEmit.Utils.DynamicILInfo), new[] { typeof(DynamicMethod), typeof(object) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [dynamicMethod]
                il.Ldarg(1); // stack: [dynamicMethod, scope]
                il.Castclass(dynamicScopeType);
                var getDynamicILInfoMethod = typeof(DynamicMethod).GetMethod("GetDynamicILInfo", BindingFlags.Instance | BindingFlags.NonPublic);
                if (getDynamicILInfoMethod == null)
                {
                    throw new MissingMethodException("DynamicMethod", "GetDynamicILInfo");
                }
                il.Call(getDynamicILInfoMethod); // stack: [dynamicMethod.GetDynamicILInfo(scope)]
                il.Ret();
            }

            return((Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo>)method.CreateDelegate(typeof(Func <DynamicMethod, object, GrEmit.Utils.DynamicILInfo>)));
        }
예제 #14
0
        private static Func <object, int, object> BuildItemGetter()
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object), typeof(int) }, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0); // stack: [scope]
                il.Castclass(dynamicScopeType);
                il.Ldarg(1); // stack: [scope, token]
                var property = dynamicScopeType.GetProperty("Item", BindingFlags.Instance | BindingFlags.NonPublic);
                if (property == null)
                {
                    throw new MissingMethodException("DynamicScope", "get_Item");
                }
                var getter = property.GetGetMethod(true);
                il.Call(getter); // stack: [scope[this]]
                il.Ret();
            }

            return((Func <object, int, object>)method.CreateDelegate(typeof(Func <object, int, object>)));
        }
예제 #15
0
        private void ProcessParameter(ParameterInfo parameterInfo, GroboIL il, int parameterMarker)
        {
            var parameterType = parameterInfo.ParameterType;

            if (parameterMarker != -1)
            {
                il.Ldarg(2); //parameters
                il.Ldc_I4(parameterMarker);
                il.Ldelem(typeof(object));
                if (parameterType.IsValueType)
                {
                    if (!IsNullable(parameterType))
                    {
                        EmitCrashIfValueIsNull(il);
                    }
                    il.Unbox_Any(parameterType);
                }
                else
                {
                    il.Castclass(parameterType);
                }
            }
            else
            {
                il.Ldarg(0); //container -> this for methods
                il.Ldarg(1); //arg0: context
                if (parameterType.IsArray)
                {
                    ProcessArray(il, parameterType.GetElementType());
                }
                else if (parameterType.IsGenericType && parameterType.GetGenericTypeDefinition() == typeof(IEnumerable <>))
                {
                    ProcessArray(il, parameterType.GetGenericArguments()[0]);
                }
                else
                {
                    ProcessNonArray(parameterInfo, il, parameterType);
                }
            }
        }
예제 #16
0
        private static void BuildGetEHInfoDelegate()
        {
            var parameterTypes = new[] { typeof(object), typeof(int), typeof(void *) };
            var method         = new DynamicMethod(Guid.NewGuid().ToString(), typeof(void), parameterTypes, typeof(string), true);

            using (var il = new GroboIL(method))
            {
                il.Ldarg(0);
                il.Castclass(dynamicResolverType);
                il.Ldarg(1);
                il.Ldarg(2);
                var getEHInfoMethod = dynamicResolverType.GetMethod("GetEHInfo", BindingFlags.Instance | BindingFlags.NonPublic);
                if (getEHInfoMethod == null)
                {
                    throw new MissingMethodException("DynamicResolver", "GetEHInfo");
                }
                il.Call(getEHInfoMethod);
                il.Ret();
            }

            getEHInfoDelegate = (GetEHInfoDelegate)method.CreateDelegate(typeof(GetEHInfoDelegate));
        }
예제 #17
0
        private static void BuildChildren(TypeBuilder typeBuilder, int n, Context context)
        {
            var property = typeBuilder.DefineProperty("Children", PropertyAttributes.None, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes);
            var getter   = typeBuilder.DefineMethod("get_Children", MethodAttributes.Public | MethodAttributes.Virtual, CallingConventions.HasThis, typeof(IEnumerable <MethodCallNode>), Type.EmptyTypes);

            using (var il = new GroboIL(getter))
            {
                il.Ldc_I4(n);                      // stack: [n]
                il.Newarr(typeof(MethodCallNode)); // stack: [new int[n] -> values]
                for (int i = 0; i < n; ++i)
                {
                    il.Dup();                          // stack: [values, values]
                    il.Ldc_I4(i);                      // stack: [values, values, i]
                    il.Ldarg(0);                       // stack: [values, values, i, this]
                    il.Ldfld(context.values[i]);       // stack: [values, values, i, this.values_{i}]
                    il.Stelem(typeof(MethodCallNode)); // values[i] = this.values_{i}; stack: [values]
                }
                il.Castclass(typeof(IEnumerable <MethodCallNode>));
                il.Ret();
            }
            property.SetGetMethod(getter);
            typeBuilder.DefineMethodOverride(getter, typeof(MethodCallNodeEdges).GetProperty(property.Name, BindingFlags.Public | BindingFlags.Instance).GetGetMethod());
        }
예제 #18
0
        public static void EmitConstructionOfType(Type type, GroboIL il)
        {
            ConstructorInfo constructor = type.GetConstructor(Type.EmptyTypes);

            if (constructor != null)
            {
                il.Newobj(constructor);
            }
            else
            {
                il.Ldtoken(type);
                il.Call(getTypeFromHandle);
                il.Call(getUninitializedObject);
                if (type.IsValueType)
                {
                    il.Unbox_Any(type);
                }
                else
                {
                    il.Castclass(type);
                }
            }
        }
예제 #19
0
        private Func <object> BuildConstants(Type type, ClosureSubstituter closureSubstituter)
        {
            var method = new DynamicMethod(Guid.NewGuid().ToString(), typeof(object), new[] { typeof(object[]) },
                                           typeof(ExpressionClosureBuilder), true);
            var root   = Expression.Parameter(type);
            var consts = new object[hashtable.Count];

            using (var il = new GroboIL(method))
            {
                il.Newobj(type.GetConstructor(Type.EmptyTypes)); // stack: [new Constants()]
                var result = il.DeclareLocal(type, "result");
                il.Stloc(result);                                // result = new Constants(); stack: []
                int index = 0;
                foreach (DictionaryEntry entry in hashtable)
                {
                    var pair      = (Tuple <Type, object>)entry.Key;
                    var constType = pair.Item1;
                    consts[index] = pair.Item2 is Expression?closureSubstituter.Visit((Expression)pair.Item2) : pair.Item2;

                    var fieldAccessor = constantsBuilder.MakeAccess(root, ((int?)entry.Value).Value);
                    var pathToField   = new List <FieldInfo>();
                    while (fieldAccessor.NodeType != ExpressionType.Parameter)
                    {
                        var memberExpression = (MemberExpression)fieldAccessor;
                        pathToField.Add((FieldInfo)memberExpression.Member);
                        fieldAccessor = memberExpression.Expression;
                    }
                    pathToField.Reverse();
                    il.Ldloc(result);
                    for (int i = 0; i < pathToField.Count - 1; ++i)
                    {
                        il.Ldflda(pathToField[i]);                            // stack: [ref result.field]
                        il.Dup();                                             // stack: [ref result.field, ref result.field]
                        var fieldType = pathToField[i].FieldType;
                        il.Ldind(fieldType);                                  // stack: [ref result.field, result.field]
                        var notNullLabel = il.DefineLabel("notNull");
                        il.Brtrue(notNullLabel);                              // if(result.field != null) goto notNull; stack: [ref result.field]
                        il.Dup();                                             // stack: [ref result.field, ref result.field]
                        il.Newobj(fieldType.GetConstructor(Type.EmptyTypes)); // stack: [ref result.field, ref result.field, new field()]
                        il.Stind(fieldType);                                  // result.field = new field(); stack: [ref result.field]
                        il.MarkLabel(notNullLabel);
                        il.Ldind(fieldType);                                  // stack: [result.field]
                    }
                    il.Ldarg(0);                                              // stack: [path, args]
                    il.Ldc_I4(index++);                                       // stack: [path, args, index]
                    il.Ldelem(typeof(object));                                // stack: [path, args[index]]
                    var field = pathToField.Last();
                    if (!constType.IsValueType)
                    {
                        il.Castclass(field.FieldType); // stack: [path, (FieldType)args[index]]
                    }
                    else
                    {
                        il.Unbox_Any(constType);
                        if (field.FieldType != constType)
                        {
                            var constructor = field.FieldType.GetConstructor(new[] { constType });
                            if (constructor == null)
                            {
                                throw new InvalidOperationException(string.Format("Missing constructor of type '{0}' with parameter of type '{1}'",
                                                                                  Formatter.Format(field.FieldType), Formatter.Format(constType)));
                            }
                            il.Newobj(constructor);
                        }
                    }
                    il.Stfld(field); // path.field = (FieldType)args[index]; stack: []
                }
                il.Ldloc(result);
                il.Ret();
            }
            var func = (Func <object[], object>)method.CreateDelegate(typeof(Func <object[], object>));

            return(() => func(consts));
        }
예제 #20
0
        private static Type BuildTypeInternal(Type type)
        {
            var parentType  = typeof(ValidationResultTreeNode);
            var properties  = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
            var typeBuilder = module.DefineType(type.Name + "_" + id++, TypeAttributes.Class | TypeAttributes.Public, parentType);

            typesBeingBuilt[type] = typeBuilder;

            var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.HasThis, new[] { parentType });

            using (var il = new GroboIL(constructor))
            {
                il.Ldarg(0);              // stack: [this]
                il.Ldarg(1);              // stack: [this, parent]
                var baseConstructor = parentType.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null, new[] { parentType }, null);
                il.Call(baseConstructor); // base(parent); stack: []
                il.Ret();
            }

            var fields = new Dictionary <string, FieldBuilder>();

            foreach (var property in properties)
            {
                var  propertyType = property.PropertyType;
                Type fieldType;
                if (propertyType.IsArray)
                {
                    fieldType = typeof(ValidationResultTreeArrayNode <>).MakeGenericType(BuildType(propertyType.GetElementType()));
                }
                else if (propertyType.IsDictionary() || propertyType == typeof(Hashtable))
                {
                    fieldType = typeof(ValidationResultTreeUniversalNode);
                }
                else
                {
                    fieldType = BuildType(propertyType, true);
                }
                var field = typeBuilder.DefineField(property.Name, fieldType, FieldAttributes.Public);
                fields.Add(property.Name, field);
            }

            var getChildrenMethod        = parentType.GetMethod("GetChildren", BindingFlags.Instance | BindingFlags.NonPublic);
            var getChildrenMethodBuilder = typeBuilder.DefineMethod(getChildrenMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, typeof(IEnumerable <KeyValuePair <object, ValidationResultTreeNode> >), Type.EmptyTypes);

            using (var il = new GroboIL(getChildrenMethodBuilder))
            {
                var listType        = typeof(List <KeyValuePair <object, ValidationResultTreeNode> >);
                var addMethod       = listType.GetMethod("Add", new[] { typeof(KeyValuePair <object, ValidationResultTreeNode>) });
                var itemConstructor = typeof(KeyValuePair <object, ValidationResultTreeNode>).GetConstructor(new[] { typeof(object), parentType });
                var list            = il.DeclareLocal(listType);
                il.Newobj(listType.GetConstructor(Type.EmptyTypes)); // stack: [new List<>()]
                il.Stloc(list);                                      // list = new List<>(); stack: []
                foreach (var field in fields.Values)
                {
                    il.Ldarg(0);                // stack: [this]
                    il.Ldfld(field);            // stack: [this.field]
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);      // if(this.field == null) goto next; stack: []
                    il.Ldloc(list);             // stack: [list]
                    il.Ldstr(field.Name);       // stack: [list, field.Name]
                    il.Ldarg(0);                // stack: [list, field.Name, this]
                    il.Ldfld(field);            // stack: [list, field.Name, this.field]
                    il.Newobj(itemConstructor); // stack: [list, new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)]
                    il.Call(addMethod);         // list.Add(new KeyValuePair<object, ValidationResultTreeNode>(field.Name, this.field)); stack: []
                    il.MarkLabel(nextLabel);
                }

                il.Ldloc(list);
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(getChildrenMethodBuilder, getChildrenMethod);

            var traverseEdgeMethod        = parentType.GetMethod("TraverseEdge", BindingFlags.Instance | BindingFlags.NonPublic);
            var traverseEdgeMethodBuilder = typeBuilder.DefineMethod(traverseEdgeMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, parentType, new[] { typeof(Expression) });

            using (var il = new GroboIL(traverseEdgeMethodBuilder))
            {
                il.Ldarg(1);                                                                   // stack: [edge]
                il.Castclass(typeof(MemberExpression));                                        // stack: [(MemberExpression)edge]
                il.Call(HackHelpers.GetProp <MemberExpression>(x => x.Member).GetGetMethod()); // stack: [((MemberExpresion)edge).Member]
                il.Call(HackHelpers.GetProp <MemberInfo>(x => x.Name).GetGetMethod());         // stack: [((MemberExpresion)edge).Member.Name]
                var member = il.DeclareLocal(typeof(string));
                il.Stloc(member);
                foreach (var property in properties)
                {
                    il.Ldstr(property.Name); // stack: [property.Name]
                    il.Ldloc(member);        // stack: [property.Name, member]
                    il.Call(typeof(string).GetMethod("op_Equality", BindingFlags.Static | BindingFlags.Public));
                    var nextLabel = il.DefineLabel("next");
                    il.Brfalse(nextLabel);           // if(property.Name != member) goto next; stack: []
                    il.Ldarg(0);                     // stack: [this]
                    il.Ldfld(fields[property.Name]); // stack: [this.field]
                    il.Ret();                        // return this.field;
                    il.MarkLabel(nextLabel);
                }

                il.Ldnull();
                il.Ret();
            }

            typeBuilder.DefineMethodOverride(traverseEdgeMethodBuilder, traverseEdgeMethod);

            var result = typeBuilder.CreateTypeInfo();

            typesBeingBuilt[type] = null;
            return(result);
        }
예제 #21
0
        public void BuildReader(ReaderTypeBuilderContext readerTypeBuilderContext)
        {
            var method = new DynamicMethod("Read_" + Type.Name + "_" + Guid.NewGuid(), typeof(void),
                                           new[]
            {
                typeof(IntPtr), typeof(int).MakeByRefType(), Type.MakeByRefType(), typeof(ReaderContext)
            }, readerTypeBuilderContext.Module, true);

            readerTypeBuilderContext.SetReaderMethod(Type, method);
            using (var il = new GroboIL(method))
            {
                var context = new ReaderMethodBuilderContext(readerTypeBuilderContext, il, !Type.IsValueType && IsReference);

                ReadTypeCodeAndCheck(context); // Read TypeCode and check

                if (!Type.IsValueType && IsReference)
                {
                    // Read reference
                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    var notReadLabel = il.DefineLabel("notRead");
                    il.Brfalse(notReadLabel);
                    context.LoadIndex();                  // stack: [external index]
                    context.LoadContext();                // stack: [external index, context]
                    il.Ldfld(ReaderContext.StartField);   // stack: [external index, context.start]
                    il.Sub();                             // stack: [external index - context.start]
                    il.Stloc(context.Index);              // index = external index - context.start; stack: []

                    context.LoadContext();                // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField); // stack: [context.objects]
                    il.Ldloc(context.Index);              // stack: [context.objects, index]
                    var obj = il.DeclareLocal(typeof(object));
                    il.Ldloca(obj);
                    object dummy;
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(index, out obj)]
                    il.Brfalse(notReadLabel);                                                                                     // if(!context.objects.TryGetValue(index, out obj)) goto notRead;
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    context.IncreaseIndexBy1();                                                                                   // Skip type code
                    context.SkipValue();                                                                                          // Skip value - it has already been read
                    il.Ret();
                    il.MarkLabel(notReadLabel);
                    il.Ldloc(context.TypeCode);               // stack: [typeCode]
                    il.Ldc_I4((int)GroBufTypeCode.Reference); // stack: [typeCode, GroBufTypeCode.Reference]
                    var readUsualLabel = il.DefineLabel("readUsual");
                    il.Bne_Un(readUsualLabel);                // if(typeCode != GroBufTypeCode.Reference) goto readUsual; stack: []

                    context.LoadContext();                    // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);     // stack: [context.objects]
                    var objectsIsNotNullLabel = il.DefineLabel("objectsIsNotNull");
                    il.Brtrue(objectsIsNotNullLabel);         // if(context.objects != null) goto objectsIsNotNull; stack: [context.objects]
                    il.Ldstr("Reference is not valid at this point");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(objectsIsNotNullLabel);

                    context.IncreaseIndexBy1(); // index = index + 1; stack: []
                    il.Ldc_I4(4);
                    context.AssertLength();
                    context.GoToCurrentLocation();
                    var reference = il.DeclareLocal(typeof(int));
                    il.Ldind(typeof(int));             // stack: [*(int*)data[index]]
                    il.Stloc(reference);               // reference = *(int*)data[index]; stack: []
                    context.IncreaseIndexBy4();        // index = index + 4; stack: []
                    il.Ldloc(context.Index);           // stack: [index]
                    il.Ldloc(reference);               // stack: [index, reference]
                    var goodReferenceLabel = il.DefineLabel("goodReference");
                    il.Bgt(goodReferenceLabel, false); // if(index > reference) goto goodReference; stack: []
                    il.Ldstr("Bad reference");
                    il.Newobj(typeof(DataCorruptedException).GetConstructor(new[] { typeof(string) }));
                    il.Throw();
                    il.MarkLabel(goodReferenceLabel);
                    context.LoadContext();                                                                                        // stack: [context]
                    il.Ldfld(ReaderContext.ObjectsField);                                                                         // stack: [context.objects]
                    il.Ldloc(reference);                                                                                          // stack: [context.objects, reference]
                    il.Ldloca(obj);                                                                                               // stack: [context.objects, reference, ref obj]
                    il.Call(HackHelpers.GetMethodDefinition <Dictionary <int, object> >(dict => dict.TryGetValue(0, out dummy))); // stack: [context.objects.TryGetValue(reference, out obj)]
                    var readObjectLabel = il.DefineLabel("readObject");
                    il.Brfalse(readObjectLabel);                                                                                  // if(!context.objects.TryGetValue(reference, out obj)) goto readObjects; stack: []
                    context.LoadResultByRef();                                                                                    // stack: [ref result]
                    il.Ldloc(obj);                                                                                                // stack: [ref result, obj]
                    il.Castclass(Type);                                                                                           // stack: [ref result, (Type)obj]
                    il.Stind(Type);                                                                                               // result = (Type)obj; stack: []
                    il.Ret();
                    il.MarkLabel(readObjectLabel);

                    // Referenced object has not been read - this means that the object reference belongs to is a property that had been deleted
                    context.LoadData();                 // stack: [data]
                    il.Ldloc(reference);                // stack: [data, reference]
                    context.LoadContext();              // stack: [data, reference, context]
                    il.Ldfld(ReaderContext.StartField); // stack: [data, reference, context.start]
                    il.Add();                           // stack: [data, reference + context.start]
                    il.Stloc(reference);                // reference += context.start; stack: [data]
                    il.Ldloca(reference);               // stack: [data, ref reference]
                    context.LoadResultByRef();          // stack: [data, ref reference, ref result]
                    context.LoadContext();              // stack: [data, ref reference, ref result, context]
                    context.CallReader(Type);
                    il.Ret();
                    il.MarkLabel(readUsualLabel);
                }

                ReadNotEmpty(context); // Read obj
                il.Ret();
            }
            var @delegate = method.CreateDelegate(typeof(ReaderDelegate <>).MakeGenericType(Type));
            var pointer   = GroBufHelpers.ExtractDynamicMethodPointer(method);

            readerTypeBuilderContext.SetReaderPointer(Type, pointer, @delegate);
        }
예제 #22
0
        private static MethodBuilder GenerateOverloadedMethodDelegate(MethodInfo methodToIntercept,
                                                                      TypeBuilder typeBuilder,
                                                                      FieldInfo concrete)
        {
            // Define the method
            var method = typeBuilder.DefineMethod(methodToIntercept.Name + "-Delegate",
                                                  MethodAttributes.Private | MethodAttributes.HideBySig,
                                                  methodToIntercept.ReturnType,
                                                  new[] { typeof(ParamInfo[]) });

            SetupGenericMethodArguments(methodToIntercept, method);

            // Local for each out/ref parameter
            var parameters = methodToIntercept.GetParameters();

            var locals = new Dictionary <string, Local>();

            using (var il = new GroboIL(method))
            {
                foreach (ParameterInfo parameter in parameters)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        locals.Add(parameter.Name, il.DeclareLocal(parameter.ParameterType.GetElementType(), parameter.Name));
                    }
                }

                var paramInfoType     = typeof(ParamInfo);
                var paramInfoGetValue = paramInfoType.GetProperty("Value").GetGetMethod();

                // Initialize out parameters to default values
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].ParameterType.IsByRef && !parameters[i].IsOut)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameters[i].ParameterType.GetElementType());
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType.GetElementType());
                        }

                        il.Stloc(locals[parameters[i].Name]);
                    }
                }

                // Load target
                il.Ldarg(0);
                il.Ldfld(concrete);

                // Push call values onto stack
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldloca(locals[parameters[i].Name]);
                    }
                    else
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoGetValue);

                        if (parameters[i].ParameterType.IsValueType || parameters[i].ParameterType.IsGenericParameter)
                        {
                            il.Unbox_Any(parameters[i].ParameterType);
                        }
                        else
                        {
                            il.Castclass(parameters[i].ParameterType);
                        }
                    }
                }

                // Call intercepted method
                il.Call(methodToIntercept);

                var paramInfoSetValue = paramInfoType.GetProperty("Value").GetSetMethod();

                // Copy out/ref parameter values back into passed-in parameters array
                for (var i = 0; i < parameters.Length; i++)
                {
                    if (parameters[i].IsOut || parameters[i].ParameterType.IsByRef)
                    {
                        il.Ldarg(1);
                        il.Ldc_I4(i);
                        il.Ldelem(paramInfoType);
                        il.Ldloc(locals[parameters[i].Name]);

                        if (parameters[i].ParameterType.GetElementType().IsValueType)
                        {
                            il.Box(parameters[i].ParameterType.GetElementType());
                        }

                        il.Call(paramInfoSetValue);
                    }
                }

                il.Ret();

                LogIlCode(il);
            }

            return(method);
        }