protected virtual void WriteInterceptorInvocationMethod(MethodInfo method, EasyMethod builder)
        {
            ArgumentReference[] arguments  = builder.Arguments;
            TypeReference[]     args       = IndirectReference.WrapIfByRef(builder.Arguments);
            LocalReference      target     = builder.CodeBuilder.DeclareLocal(this.Context.Invocation);
            EasyCallable        callable   = this._method2Delegate[method] as EasyCallable;
            FieldReference      reference2 = this.ObtainCallableFieldBuilderDelegate(callable);

            builder.CodeBuilder.AddStatement(new AssignStatement(target, new MethodInvocationExpression(this._method2Invocation, new Expression[] { reference2.ToExpression(), new MethodTokenExpression(this.GetCorrectMethod(method)), this.GetPseudoInvocationTarget(method) })));
            LocalReference reference3 = builder.CodeBuilder.DeclareLocal(typeof(object));
            LocalReference reference4 = builder.CodeBuilder.DeclareLocal(typeof(object[]));

            builder.CodeBuilder.AddStatement(new AssignStatement(reference4, new ReferencesToObjectArrayExpression(args)));
            builder.CodeBuilder.AddStatement(new AssignStatement(reference3, new VirtualMethodInvocationExpression(this.InterceptorField, this.Context.Interceptor.GetMethod("Intercept"), new Expression[] { target.ToExpression(), reference4.ToExpression() })));
            for (int i = 0; i < arguments.Length; i++)
            {
                if (arguments[i].Type.IsByRef)
                {
                    builder.CodeBuilder.AddStatement(new AssignStatement(args[i], new ConvertExpression(args[i].Type, new LoadRefArrayElementExpression(i, reference4))));
                }
            }
            if (builder.ReturnType == typeof(void))
            {
                builder.CodeBuilder.AddStatement(new ReturnStatement());
            }
            else
            {
                builder.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(builder.ReturnType, reference3.ToExpression())));
            }
        }
        /// <summary>
        /// Writes the method implementation. This
        /// method generates the IL code for property get/set method and
        /// ordinary methods.
        /// </summary>
        /// <param name="method">The method to implement.</param>
        /// <param name="builder"><see cref="EasyMethod"/> being constructed.</param>
        protected virtual void WriteInterceptorInvocationMethod(MethodInfo method, EasyMethod builder)
        {
            ArgumentReference[] arguments             = builder.Arguments;
            TypeReference[]     dereferencedArguments = IndirectReference.WrapIfByRef(builder.Arguments);

            LocalReference local_inv = builder.CodeBuilder.DeclareLocal(Context.Invocation);

            EasyCallable   callable      = _method2Delegate[method] as EasyCallable;
            FieldReference fieldDelegate = ObtainCallableFieldBuilderDelegate(callable);

            builder.CodeBuilder.AddStatement(
                new AssignStatement(local_inv,
                                    new MethodInvocationExpression(_method2Invocation,
                                                                   fieldDelegate.ToExpression(),
                                                                   new MethodTokenExpression(GetCorrectMethod(method)),
                                                                   GetPseudoInvocationTarget(method))));

            LocalReference ret_local  = builder.CodeBuilder.DeclareLocal(typeof(object));
            LocalReference args_local = builder.CodeBuilder.DeclareLocal(typeof(object[]));

            // Store arguments into an object array.
            builder.CodeBuilder.AddStatement(
                new AssignStatement(args_local,
                                    new ReferencesToObjectArrayExpression(dereferencedArguments)));

            // Invoke the interceptor.
            builder.CodeBuilder.AddStatement(
                new AssignStatement(ret_local,
                                    new VirtualMethodInvocationExpression(InterceptorField,
                                                                          Context.Interceptor.GetMethod("Intercept"),
                                                                          local_inv.ToExpression(),
                                                                          args_local.ToExpression())));

            // Load possibly modified ByRef arguments from the array.
            for (int i = 0; i < arguments.Length; i++)
            {
                if (arguments[i].Type.IsByRef)
                {
                    builder.CodeBuilder.AddStatement(
                        new AssignStatement(dereferencedArguments[i],
                                            new ConvertExpression(dereferencedArguments[i].Type,
                                                                  new LoadRefArrayElementExpression(i, args_local))));
                }
            }

            if (builder.ReturnType == typeof(void))
            {
                builder.CodeBuilder.AddStatement(new ReturnStatement());
            }
            else
            {
                builder.CodeBuilder.AddStatement(new ReturnStatement(
                                                     new ConvertExpression(builder.ReturnType, ret_local.ToExpression())));
            }
        }
        private void GenerateCall()
        {
            ArgumentReference arrayReference = new ArgumentReference(typeof(object[]));

            this._callmethod = base.CreateMethod("Call", new ReturnReferenceExpression(typeof(object)), new ArgumentReference[] { arrayReference });
            TypeReference[]  referenceArray  = IndirectReference.WrapIfByRef(this._args);
            LocalReference[] referenceArray2 = new LocalReference[this._args.Length];
            Expression[]     args            = new Expression[this._args.Length];
            for (int i = 0; i < this._args.Length; i++)
            {
                if (this._args[i].Type.IsByRef)
                {
                    referenceArray2[i] = this._callmethod.CodeBuilder.DeclareLocal(referenceArray[i].Type);
                    this._callmethod.CodeBuilder.AddStatement(new AssignStatement(referenceArray2[i], new ConvertExpression(referenceArray[i].Type, new LoadRefArrayElementExpression(i, arrayReference))));
                    args[i] = referenceArray2[i].ToAddressOfExpression();
                }
                else
                {
                    args[i] = new ConvertExpression(referenceArray[i].Type, new LoadRefArrayElementExpression(i, arrayReference));
                }
            }
            MethodInvocationExpression expression = new MethodInvocationExpression(this._invokeMethod, args);
            Expression instance = null;

            if (this._returnType.Type == typeof(void))
            {
                this._callmethod.CodeBuilder.AddStatement(new ExpressionStatement(expression));
                instance = NullExpression.Instance;
            }
            else
            {
                LocalReference target = this._callmethod.CodeBuilder.DeclareLocal(typeof(object));
                this._callmethod.CodeBuilder.AddStatement(new AssignStatement(target, new ConvertExpression(typeof(object), this._returnType.Type, expression)));
                instance = target.ToExpression();
            }
            for (int j = 0; j < this._args.Length; j++)
            {
                if (this._args[j].Type.IsByRef)
                {
                    this._callmethod.CodeBuilder.AddStatement(new AssignArrayStatement(arrayReference, j, new ConvertExpression(typeof(object), referenceArray[j].Type, referenceArray2[j].ToExpression())));
                }
            }
            this._callmethod.CodeBuilder.AddStatement(new ReturnStatement(instance));
        }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                ProxyGenerationOptions options, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition());
            var genericArguments = TypeExtender.EmptyTypes;

            var constructor = invocation.GetConstructors()[0];

            Expression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // bind generic method arguments to invocation's type arguments
                genericArguments = emitter.MethodBuilder.GetGenericArguments();
                invocationType   = invocationType.MakeGenericType(genericArguments);

                constructor = TypeBuilder.GetConstructor(invocationType, constructor);

                // Not in the cache: generic method
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name),
                                                                  typeof(IMethodInfo));

                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken,
                                                                                     new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken.ToExpression();
            }

            var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);
            var hasByRefArguments     = HasByRefArguments(emitter.Arguments);

            var arguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression,
                                             dereferencedArguments);
            var ctorArguments = ModifyArguments(@class, arguments);

            var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);

            emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
                                                                 new NewInstanceExpression(constructor, ctorArguments)));

            if (MethodToOverride.ContainsGenericParameters)
            {
                EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new TryStatement());
            }

            var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed));

            emitter.CodeBuilder.AddStatement(proceed);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new FinallyStatement());
            }

            GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement());
            }

            if (MethodToOverride.ReturnType != typeof(void))
            {
                var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);
                emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition);
            var genericArguments = Type.EmptyTypes;

            var constructor = invocation.GetConstructors()[0];

            Expression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // bind generic method arguments to invocation's type arguments
                genericArguments = emitter.MethodBuilder.GetGenericArguments();
                invocationType   = invocationType.MakeGenericType(genericArguments);
                constructor      = TypeBuilder.GetConstructor(invocationType, constructor);

                // Not in the cache: generic method
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name), typeof(MethodInfo));
                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken, new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken.ToExpression();
            }

            var methodInterceptors = SetMethodInterceptors(@class, namingScope, emitter, proxiedMethodTokenExpression);

            var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);
            var hasByRefArguments     = HasByRefArguments(emitter.Arguments);

            var arguments     = GetCtorArguments(@class, proxiedMethodTokenExpression, dereferencedArguments, methodInterceptors);
            var ctorArguments = ModifyArguments(@class, arguments);

            var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);

            emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
                                                                 new NewInstanceExpression(constructor, ctorArguments)));

            if (MethodToOverride.ContainsGenericParameters)
            {
                EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new TryStatement());
            }

            var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed));

            emitter.CodeBuilder.AddStatement(proceed);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new FinallyStatement());
            }

            GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement());
            }

            if (MethodToOverride.ReturnType != typeof(void))
            {
                var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);

                // Emit code to ensure a value type return type is not null, otherwise the cast will cause a null-deref
                if (emitter.ReturnType.IsValueType && !emitter.ReturnType.IsNullableType())
                {
                    LocalReference returnValue = emitter.CodeBuilder.DeclareLocal(typeof(object));
                    emitter.CodeBuilder.AddStatement(new AssignStatement(returnValue, getRetVal));

                    emitter.CodeBuilder.AddExpression(new IfNullExpression(returnValue, new ThrowStatement(typeof(InvalidOperationException),
                                                                                                           "Interceptors failed to set a return value, or swallowed the exception thrown by the target")));
                }

                // Emit code to return with cast from ReturnValue
                emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }
Exemple #6
0
        private void GenerateCall()
        {
            ArgumentReference arg = new ArgumentReference(typeof(object[]));

            _callmethod = CreateMethod("Call",
                                       new ReturnReferenceExpression(typeof(object)), arg);

            // LocalReference localRef = method.CodeBuilder.DeclareLocal( typeof(object) );

            TypeReference[]  dereferencedArguments = IndirectReference.WrapIfByRef(_args);
            LocalReference[] localCopies           = new LocalReference[_args.Length];
            Expression[]     invocationArguments   = new Expression[_args.Length];

            // Load arguments from the object array.
            for (int i = 0; i < _args.Length; i++)
            {
                if (_args[i].Type.IsByRef)
                {
                    localCopies[i] = _callmethod.CodeBuilder.DeclareLocal(dereferencedArguments[i].Type);

                    _callmethod.CodeBuilder.AddStatement(new AssignStatement(localCopies[i],
                                                                             new ConvertExpression(dereferencedArguments[i].Type,
                                                                                                   new LoadRefArrayElementExpression(i, arg))));

                    invocationArguments[i] = localCopies[i].ToAddressOfExpression();
                }
                else
                {
                    invocationArguments[i] = new ConvertExpression(dereferencedArguments[i].Type,
                                                                   new LoadRefArrayElementExpression(i, arg));
                }
            }

            // Invoke the method.
            MethodInvocationExpression methodInv = new MethodInvocationExpression(
                _invokeMethod,
                invocationArguments);

            Expression result = null;

            if (_returnType.Type == typeof(void))
            {
                _callmethod.CodeBuilder.AddStatement(new ExpressionStatement(methodInv));
                result = NullExpression.Instance;
            }
            else
            {
                LocalReference resultLocal = _callmethod.CodeBuilder.DeclareLocal(typeof(object));

                _callmethod.CodeBuilder.AddStatement(new AssignStatement(resultLocal,
                                                                         new ConvertExpression(typeof(object), _returnType.Type, methodInv)));

                result = resultLocal.ToExpression();
            }

            // Save ByRef arguments into the object array.
            for (int i = 0; i < _args.Length; i++)
            {
                if (_args[i].Type.IsByRef)
                {
                    _callmethod.CodeBuilder.AddStatement(new AssignArrayStatement(arg, i,
                                                                                  new ConvertExpression(typeof(object), dereferencedArguments[i].Type,
                                                                                                        localCopies[i].ToExpression())));
                }
            }

            // Return.
            _callmethod.CodeBuilder.AddStatement(new ReturnStatement(result));
        }
Exemple #7
0
        protected override MethodEmitter BuildProxiedMethodBody(MethodEmitter emitter, ClassEmitter @class,
                                                                ProxyGenerationOptions options, INamingScope namingScope)
        {
            var invocationType = invocation;

            Trace.Assert(MethodToOverride.IsGenericMethod == invocationType.IsGenericTypeDefinition());
            var genericArguments = TypeExtender.EmptyTypes;

            var constructor = invocation.GetConstructors()[0];

            Expression proxiedMethodTokenExpression;

            if (MethodToOverride.IsGenericMethod)
            {
                // bind generic method arguments to invocation's type arguments
                genericArguments = emitter.MethodBuilder.GetGenericArguments();
                invocationType   = invocationType.MakeGenericType(genericArguments);
                constructor      = TypeBuilder.GetConstructor(invocationType, constructor);

                // Not in the cache: generic method
                proxiedMethodTokenExpression = new MethodTokenExpression(MethodToOverride.MakeGenericMethod(genericArguments));
            }
            else
            {
                var proxiedMethodToken = @class.CreateStaticField(namingScope.GetUniqueName("token_" + MethodToOverride.Name),
                                                                  typeof(MethodInfo));
                @class.ClassConstructor.CodeBuilder.AddStatement(new AssignStatement(proxiedMethodToken,
                                                                                     new MethodTokenExpression(MethodToOverride)));

                proxiedMethodTokenExpression = proxiedMethodToken.ToExpression();
            }

            var dereferencedArguments = IndirectReference.WrapIfByRef(emitter.Arguments);
            var hasByRefArguments     = HasByRefArguments(emitter.Arguments);

            var arguments = GetCtorArguments(@class, namingScope, proxiedMethodTokenExpression,
                                             dereferencedArguments);
            var ctorArguments = ModifyArguments(@class, arguments);

            var invocationLocal = emitter.CodeBuilder.DeclareLocal(invocationType);

            emitter.CodeBuilder.AddStatement(new AssignStatement(invocationLocal,
                                                                 new NewInstanceExpression(constructor, ctorArguments)));

            if (MethodToOverride.ContainsGenericParameters)
            {
                EmitLoadGenricMethodArguments(emitter, MethodToOverride.MakeGenericMethod(genericArguments), invocationLocal);
            }

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new TryStatement());
            }

            var proceed = new ExpressionStatement(new MethodInvocationExpression(invocationLocal, InvocationMethods.Proceed));

            emitter.CodeBuilder.AddStatement(proceed);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new FinallyStatement());
            }

            GeneratorUtil.CopyOutAndRefParameters(dereferencedArguments, invocationLocal, MethodToOverride, emitter);

            if (hasByRefArguments)
            {
                emitter.CodeBuilder.AddStatement(new EndExceptionBlockStatement());
            }

            if (MethodToOverride.ReturnType != typeof(void))
            {
                // Emit code to return with cast from ReturnValue

                // @mbrit - 2012-05-31 - see the note associated with the GetReturnValueForWinRt declaration
                // for more information on this...

                var useWinRtGenericHandler = false;
#if NETFX_CORE
                if (emitter.ReturnType == typeof(int) || emitter.ReturnType == typeof(bool))
                {
                    useWinRtGenericHandler = true;
                }
#endif
                if (!(useWinRtGenericHandler))
                {
                    var getRetVal = new MethodInvocationExpression(invocationLocal, InvocationMethods.GetReturnValue);
                    emitter.CodeBuilder.AddStatement(new ReturnStatement(new ConvertExpression(emitter.ReturnType, getRetVal)));
                }
                else
                {
#if NETFX_CORE
                    var grvArgs   = new Type[] { emitter.ReturnType };
                    var grvCall   = InvocationMethods.GetReturnValueForWinRt.MakeGenericMethod(grvArgs);
                    var getRetVal = new MethodInvocationExpression(invocationLocal, grvCall);
                    emitter.CodeBuilder.AddStatement(new ReturnStatement(getRetVal));
#endif
                }
            }
            else
            {
                emitter.CodeBuilder.AddStatement(new ReturnStatement());
            }

            return(emitter);
        }