예제 #1
0
        public void TestZzz2()
        {
            var asm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);

            var mod  = asm.DefineDynamicModule("mymod", "tmp.dll", true);
            var type = mod.DefineType("baz", TypeAttributes.Public | TypeAttributes.Class);
            var meth = type.DefineMethod("go", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(int) });

            var document = mod.DefineDocument("TestDebug2.txt", Guid.Empty, Guid.Empty, Guid.Empty); //Expression.SymbolDocument("TestDebug2.txt");

            //var di = Expression.DebugInfo(sdi, 2, 2, 2, 13);

            //var exp = Expression.Divide(Expression.Constant(2), Expression.Subtract(Expression.Constant(4), Expression.Constant(4)));
            //var block = Expression.Block(di, exp);

            using (var il = new GroboIL(meth))
            {
//                        nop                      // []
//        nop                      // []
//        ldc.i4.1                 // [Int32]
//        brfalse ifFalse_7        // []
//        nop                      // []
//        ldarg.0                  // [Int32]
//        br done_10               // [Int32]
//ifFalse_7:                       // []
//        nop                      // []
//        ldarg.0                  // [Int32]
//done_10:                         // [Int32]
//        stloc local_0            // []
//        nop                      // []
//        ldloc local_0            // [Int32]
//        ret                      // []

//                var tst = Expression.Block(Expression.DebugInfo(sdi, 6, 20, 6, 27), Expression.Constant(true));
//                var iftrue = Expression.Block(Expression.DebugInfo(sdi, 10, 20, 10, 26), variable);
//                var iffalse = Expression.Block(Expression.DebugInfo(sdi, 14, 20, 14, 26), variable);
//                var exp = Expression.Condition(tst, iftrue, iffalse);
//
//                /*
//                var returnTarget = Expression.Label(typeof(int));
//                var returnExpression = Expression.Return(returnTarget, exp, typeof(int));
//                var returnLabel = Expression.Label(returnTarget, Expression.Constant(0));
//                */
//
//                var block = Expression.Block(typeof(int), new[] { temp },
//                    Expression.DebugInfo(sdi, 4, 15, 4, 16), Expression.Assign(temp, exp), Expression.DebugInfo(sdi, 17, 16, 17, 21), temp);
//                //var block = Expression.Block(Expression.DebugInfo(sdi, 4, 16, 17, 10), Expression.Assign(temp, exp)));
//                var kek = Expression.Lambda(block, variable);

                il.MarkSequencePoint(document, 4, 15, 4, 16);
                il.Nop();
                il.Nop();
                il.Ldc_I4(1);
                il.MarkSequencePoint(document, 6, 20, 6, 27);
                var brFalse = il.DefineLabel("brFalse");
                il.Brfalse(brFalse);
                il.MarkSequencePoint(document, 10, 20, 10, 26);
                il.Nop();
                il.Ldarg(0);
                il.Ldc_I4(100);
                il.Add();
                var doneLabel = il.DefineLabel("done");
                il.Br(doneLabel);
                il.MarkSequencePoint(document, 14, 20, 14, 26);
                il.MarkLabel(brFalse);
                il.Nop();
                il.Ldarg(0);
                il.Ldc_I4(10);
                il.Add();
                il.MarkLabel(doneLabel);
                il.MarkSequencePoint(document, 16, 16, 16, 21);
                var local = il.DeclareLocal(typeof(int));
                il.Stloc(local);
                il.Nop();
                il.MarkSequencePoint(document, 17, 16, 17, 21);
                il.Ldloc(local);
                il.Ret();
            }

            var newtype = type.CreateType();

            asm.Save("tmp.dll");
            newtype.GetMethod("go").Invoke(null, new object[] { 0 });
            //meth.Invoke(null, new object[0]);
            //lambda.DynamicInvoke(new object[0]);
            Console.WriteLine(" ");
        }
예제 #2
0
        /// <summary>
        /// Builds Proxy Type that implement an interface, and proxy calls to defined with attribute
        /// methods via defined intercepting handlers
        /// </summary>
        /// <param name="interface">Type to wrap</param>
        /// <param name="implementation">
        /// Type providing interface implementation, intercepting attributes are read from this type
        /// </param>
        /// <returns>
        /// Proxy type with constructor accepting object implementing @interface and intercepting
        /// handlers as parameters
        /// </returns>
        public static Type CreateInterfaceProxy(Type @interface, Type implementation)
        {
            Contract.Ensures(Contract.Result <Type>() != null);
            if ([email protected])
            {
                throw new ArgumentException($"{nameof(@interface)} ({@interface.FullName}) is not an interface.");
            }

            if ([email protected](implementation))
            {
                throw new ArgumentException($"{nameof(@interface)} ({@interface.FullName}) is not assignable from {nameof(implementation)} ({implementation.FullName})");
            }
            var typeName    = $"{@interface.Assembly.GetName().Name}.v{@interface.Assembly.GetName().Version}.{@interface.FullName}";
            var typeBuilder = ModuleBuilder.DefineType($"InterceptorProxy_{typeName}_{Guid.NewGuid().ToString("N")}", TypeAttributes.Class | TypeAttributes.Public);

            typeBuilder.AddInterfaceImplementation(SetupGenericClassArguments(@interface, typeBuilder));

            var methods = new List <MethodPair>();

            AddMethodPairsToList(methods, @interface, implementation);

            var methodInterceptors = new Dictionary <MethodInfo, Type[]>();
            var interceptorFields  = new Dictionary <Type, FieldInfo>();

            var methodsCount      = methods.Count;
            var attributesHashSet = new HashSet <Type>();

            for (var i = 0; i < methodsCount; i++)
            {
                var method          = methods[i];
                var interfaceMethod = method.InterfaceMethod;
                var typeMethod      = method.TargetMethod;

                var attributeTypes = Attribute.GetCustomAttributes(typeMethod, typeof(InterceptorAttribute), true)
                                     .OrderBy(a => ((InterceptorAttribute)a).Order).Select(a => ((InterceptorAttribute)a).InterceptionHandlerType).ToArray();

                for (int j = 0; j < attributeTypes.Length; j++)
                {
                    if (!typeof(IInterceptionHandler).IsAssignableFrom(attributeTypes[j]))
                    {
                        throw new InvalidOperationException($"Interception handler type should implement {nameof(IInterceptionHandler)} interface");
                    }
                }

                attributesHashSet.UnionWith(attributeTypes);
                methodInterceptors.Add(interfaceMethod, attributeTypes);
            }

            var baseConstructorInfo = typeof(object).GetConstructor(Type.EmptyTypes);

            var intercpetionHandlerType = typeof(IInterceptionHandler);

            var genericInterceptionAction = intercpetionHandlerType.GetMethods().Single(i => i.Name == "InterceptingAction" && i.ReturnType != typeof(void));
            var voidInterceptionAction    = intercpetionHandlerType.GetMethods().Single(i => i.Name == "InterceptingAction" && i.ReturnType == typeof(void));

            var att = attributesHashSet.ToList();

            att.Insert(0, implementation);
            var paramArray = att.ToArray();

            var constructorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramArray);
            var concrete           = typeBuilder.DefineField("Concrete", @interface, FieldAttributes.Public);

            for (int i = 1; i < paramArray.Length; i++)
            {
                var at = paramArray[i];
                interceptorFields.Add(at, typeBuilder.DefineField(at.Name, intercpetionHandlerType, FieldAttributes.Public));
            }

            GroboIL il;

            using (il = new GroboIL(constructorBuilder))
            {
                il.Ldarg(0);
                il.Call(baseConstructorInfo);
                il.Nop();

                // set concrete
                il.Ldarg(0);
                il.Ldarg(1);
                il.Stfld(concrete);

                // set injected interceptionHandlers
                for (var i = 1; i < paramArray.Length; i++)
                {
                    il.Ldarg(0);
                    il.Ldarg(i + 1);
                    il.Stfld(interceptorFields[paramArray[i]]);
                }

                il.Ret();

                LogIlCode(il);
            }

            for (var i = 0; i < methodsCount; i++)
            {
                var interfaceMethod = methods[i].InterfaceMethod;

                if (interfaceMethod.IsGenericMethod)
                {
                    interfaceMethod = interfaceMethod.GetGenericMethodDefinition();
                }

                DefineMethodOverride(typeBuilder, interfaceMethod, methodInterceptors, interceptorFields, genericInterceptionAction, voidInterceptionAction, concrete);
            }

            return(typeBuilder.CreateTypeInfo().AsType());
        }
예제 #3
0
        public void TestZzz()
        {
            var asm = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("foo"), AssemblyBuilderAccess.RunAndSave);

            var mod  = asm.DefineDynamicModule("mymod", "tmp.dll", true);
            var type = mod.DefineType("baz", TypeAttributes.Public | TypeAttributes.Class);
            var meth = type.DefineMethod("go", MethodAttributes.Public | MethodAttributes.Static, typeof(int), new[] { typeof(int) });

            var document = mod.DefineDocument("TestDebug2.txt", Guid.Empty, Guid.Empty, Guid.Empty); //Expression.SymbolDocument("TestDebug2.txt");

            meth.DefineParameter(1, ParameterAttributes.In, "$x");

            //var di = Expression.DebugInfo(sdi, 2, 2, 2, 13);

            //var exp = Expression.Divide(Expression.Constant(2), Expression.Subtract(Expression.Constant(4), Expression.Constant(4)));
            //var block = Expression.Block(di, exp);

            using (var il = new GroboIL(meth))
            {
//                var tst = Expression.Block(Expression.DebugInfo(sdi, 6, 20, 6, 27), Expression.Equal(variable, zero));
//                var iftrue = Expression.Block(Expression.DebugInfo(sdi, 10, 20, 10, 26), Expression.Add(variable, two));
//                var iffalse = Expression.Block(Expression.DebugInfo(sdi, 14, 20, 14, 26), Expression.Divide(variable, two));
//                var exp = Expression.Condition(tst, iftrue, iffalse);
//                var block = Expression.Block(Expression.DebugInfo(sdi, 4, 16, 15, 10), exp);

//                        nop                      // []
//        nop                      // []
//        ldarg.0                  // [Int32]
//        ldc.i4.0                 // [Int32, Int32]
//        ceq                      // [Int32]
//        brfalse ifFalse_5        // []
//        nop                      // []
//        ldarg.0                  // [Int32]
//        ldc.i4.2                 // [Int32, Int32]
//        add                      // [Int32]
//        br done_8                // [Int32]
//ifFalse_5:                       // []
//        nop                      // []
//        ldarg.0                  // [Int32]
//        ldc.i4.2                 // [Int32, Int32]
//        div                      // [Int32]
//done_8:                          // [Int32]
//        ret                      // []

                il.MarkSequencePoint(document, 3, 9, 3, 15);
                il.Nop();
                il.MarkSequencePoint(document, 4, 13, 4, 19);
                il.Nop();
                il.Ldarg(0);
                il.Ldc_I4(0);
                il.Ceq();
                var label = il.DefineLabel("ifFalse");
                il.Brfalse(label);
                il.MarkSequencePoint(document, 7, 13, 7, 19);
                il.Nop();
                il.Ldarg(0);
                il.Ldc_I4(2);
                il.Add();
                var doneLabel = il.DefineLabel("done");
                il.Br(doneLabel);
                il.MarkLabel(label);
                il.MarkSequencePoint(document, 10, 13, 10, 19);
                il.Nop();
                il.Ldarg(0);
                il.Ldc_I4(2);
                il.Mul();
                il.MarkLabel(doneLabel);
                il.MarkSequencePoint(document, 12, 5, 12, 6);
                il.Nop();
                il.Ret();
            }

            var newtype = type.CreateType();

            asm.Save("tmp.dll");
            newtype.GetMethod("go").Invoke(null, new object[] { 0 });
            //meth.Invoke(null, new object[0]);
            //lambda.DynamicInvoke(new object[0]);
            Console.WriteLine(" ");
        }
예제 #4
0
        private static void DefineMethodOverrideWithInterception(TypeBuilder typeBuilder, MethodBuilder methodBuilder, MethodInfo overridedMethod, Dictionary <Type, FieldInfo> interceptorFields, MethodInfo genericInterceptionAction, MethodInfo voidInterceptionAction, FieldBuilder concreteInstance, ParameterInfo[] methodParams, Type[] genericParameterTypes, Type[] interceptors)
        {
            var @delegate = GenerateOverloadedMethodDelegate(overridedMethod, typeBuilder, concreteInstance);

            for (var i = 0; i < interceptors.Length; i++)
            {
                var interceptor = interceptors[i];

                @delegate = DefineMethodInterceptingDelegate(typeBuilder, overridedMethod, interceptorFields, genericInterceptionAction, voidInterceptionAction, genericParameterTypes, @delegate, i, interceptor);
            }

            using (var il = new GroboIL(methodBuilder))
            {
                var paramInfoType  = typeof(ParamInfo);
                var paramsInfoType = typeof(ParamInfo[]);
                var paramsInfo     = il.DeclareLocal(paramsInfoType);
                var paramInfo      = il.DeclareLocal(paramInfoType);

                il.Nop();

                il.Ldc_I4(methodParams.Length);
                il.Newarr(typeof(ParamInfo));
                il.Stloc(paramsInfo);

                var paramInfoConstructor = paramInfoType.GetConstructor(new[] { typeof(string), typeof(Type), typeof(bool), typeof(bool) });
                var paramInfoValueSetter = paramInfoType.GetProperty("Value").GetSetMethod();
                var getTypeMethod        = typeof(Type).GetMethod("GetTypeFromHandle", new[] { typeof(RuntimeTypeHandle) });

                var idx = 0;
                foreach (var parameter in methodParams)
                {
                    // load array at index
                    il.Ldloc(paramsInfo);
                    il.Ldc_I4(idx++);

                    // Load ParamInfo.Name
                    il.Ldstr(parameter.Name);

                    // Load ParamInfo.Type
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldtoken(parameter.ParameterType.GetElementType());
                    }
                    else
                    {
                        il.Ldtoken(parameter.ParameterType);
                    }

                    il.Call(getTypeMethod);

                    // Load ParamInfo.IsByRef
                    if (parameter.ParameterType.IsByRef)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // Load ParamInfo.IsOut
                    if (parameter.IsOut)
                    {
                        il.Ldc_I4(1);
                    }
                    else
                    {
                        il.Ldc_I4(0);
                    }

                    // instantiate ParamInfo
                    il.Newobj(paramInfoConstructor);
                    il.Stloc(paramInfo);

                    // Set ParamInfo.Value
                    il.Ldloc(paramInfo);
                    il.Ldarg(parameter.Position + 1);
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldobj(parameter.ParameterType.GetElementType());

                        if (parameter.ParameterType.GetElementType().IsValueType || parameter.ParameterType.GetElementType().IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType.GetElementType());
                        }
                    }
                    else
                    {
                        if (parameter.ParameterType.IsValueType || parameter.ParameterType.IsGenericParameter)
                        {
                            il.Box(parameter.ParameterType);
                        }
                    }

                    il.Call(paramInfoValueSetter);
                    il.Nop();

                    // push to array
                    il.Ldloc(paramInfo);
                    il.Stelem(paramInfoType);
                }

                il.Ldarg(0);
                il.Ldloc(paramsInfo);
                if (overridedMethod.IsGenericMethodDefinition)
                {
                    il.Call(@delegate.MakeGenericMethod(genericParameterTypes));
                }
                else
                {
                    il.Call(@delegate);
                }

                idx = 1;
                var paramInfoValueGetter = paramInfoType.GetProperty("Value").GetGetMethod();
                foreach (var parameter in methodParams)
                {
                    if (parameter.IsOut || parameter.ParameterType.IsByRef)
                    {
                        il.Ldarg(idx);
                        il.Ldloc(paramsInfo);
                        il.Ldc_I4(idx - 1);
                        il.Ldelem(paramInfoType);
                        il.Call(paramInfoValueGetter);

                        if (parameter.ParameterType.GetElementType().IsValueType)
                        {
                            il.Unbox_Any(parameter.ParameterType.GetElementType());
                        }

                        il.Stobj(parameter.ParameterType.GetElementType());
                    }

                    idx++;
                }

                il.Ret();

                LogIlCode(il);
            }
        }