コード例 #1
0
        protected virtual void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters,
                                                             MethodEmitter invokeMethodOnTarget,
                                                             Reference targetField)
        {
            var callbackMethod = GetCallbackMethod(invocation);

            if (callbackMethod == null)
            {
                EmitCallThrowOnNoTarget(invokeMethodOnTarget);
                return;
            }

            var args = new IExpression[parameters.Length];

            // Idea: instead of grab parameters one by one
            // we should grab an array
            var byRefArguments = new Dictionary <int, LocalReference>();

            for (var i = 0; i < parameters.Length; i++)
            {
                var param = parameters[i];

                var paramType = invocation.GetClosedParameterType(param.ParameterType);
                if (paramType.IsByRef)
                {
                    var localReference = invokeMethodOnTarget.CodeBuilder.DeclareLocal(paramType.GetElementType());
                    invokeMethodOnTarget.CodeBuilder
                    .AddStatement(
                        new AssignStatement(localReference,
                                            new ConvertExpression(paramType.GetElementType(),
                                                                  new MethodInvocationExpression(SelfReference.Self,
                                                                                                 InvocationMethods.GetArgumentValue,
                                                                                                 new LiteralIntExpression(i)))));
                    var byRefReference = new ByRefReference(localReference);
                    args[i]           = byRefReference;
                    byRefArguments[i] = localReference;
                }
                else
                {
                    args[i] =
                        new ConvertExpression(paramType,
                                              new MethodInvocationExpression(SelfReference.Self,
                                                                             InvocationMethods.GetArgumentValue,
                                                                             new LiteralIntExpression(i)));
                }
            }

            if (byRefArguments.Count > 0)
            {
                invokeMethodOnTarget.CodeBuilder.AddStatement(new TryStatement());
            }

            var methodOnTargetInvocationExpression = GetCallbackMethodInvocation(invocation, args, callbackMethod, targetField, invokeMethodOnTarget);

            LocalReference returnValue = null;

            if (callbackMethod.ReturnType != typeof(void))
            {
                var returnType = invocation.GetClosedParameterType(callbackMethod.ReturnType);
                returnValue = invokeMethodOnTarget.CodeBuilder.DeclareLocal(returnType);
                invokeMethodOnTarget.CodeBuilder.AddStatement(new AssignStatement(returnValue, methodOnTargetInvocationExpression));
            }
            else
            {
                invokeMethodOnTarget.CodeBuilder.AddStatement(methodOnTargetInvocationExpression);
            }

            AssignBackByRefArguments(invokeMethodOnTarget, byRefArguments);

            if (callbackMethod.ReturnType != typeof(void))
            {
                var setRetVal =
                    new MethodInvocationExpression(SelfReference.Self,
                                                   InvocationMethods.SetReturnValue,
                                                   new ConvertExpression(typeof(object), returnValue.Type, returnValue));

                invokeMethodOnTarget.CodeBuilder.AddStatement(setRetVal);
            }

            invokeMethodOnTarget.CodeBuilder.AddStatement(new ReturnStatement());
        }
コード例 #2
0
        protected virtual void ImplementInvokeMethodOnTarget(AbstractTypeEmitter invocation, ParameterInfo[] parameters,
                                                             MethodEmitter invokeMethodOnTarget,
                                                             Reference targetField)
        {
            var callbackMethod = GetCallbackMethod(invocation);

            if (callbackMethod == null)
            {
                EmitCallThrowOnNoTarget(invokeMethodOnTarget);
                return;
            }

            if (canChangeTarget)
            {
                EmitCallEnsureValidTarget(invokeMethodOnTarget);
            }

            Expression[] args = new Expression[parameters.Length];

            // Idea: instead of grab parameters one by one
            // we should grab an array
            Dictionary <int, LocalReference> byRefArguments = new Dictionary <int, LocalReference>();

            for (int i = 0; i < parameters.Length; i++)
            {
                ParameterInfo param = parameters[i];

                Type paramType = invocation.GetClosedParameterType(param.ParameterType);
                if (paramType.IsByRef)
                {
                    LocalReference localReference = invokeMethodOnTarget.CodeBuilder.DeclareLocal(paramType.GetElementType());
                    invokeMethodOnTarget.CodeBuilder
                    .AddStatement(
                        new AssignStatement(localReference,
                                            new ConvertExpression(paramType.GetElementType(),
                                                                  new MethodInvocationExpression(SelfReference.Self,
                                                                                                 InvocationMethods.GetArgumentValue,
                                                                                                 new LiteralIntExpression(i)))));
                    ByRefReference byRefReference = new ByRefReference(localReference);
                    args[i]           = new ReferenceExpression(byRefReference);
                    byRefArguments[i] = localReference;
                }
                else
                {
                    args[i] =
                        new ConvertExpression(paramType,
                                              new MethodInvocationExpression(SelfReference.Self,
                                                                             InvocationMethods.GetArgumentValue,
                                                                             new LiteralIntExpression(i)));
                }
            }

            var methodOnTargetInvocationExpression = GetCallbackMethodInvocation(invocation, args, callbackMethod, targetField,
                                                                                 invokeMethodOnTarget);

            LocalReference returnValue = null;

            if (callbackMethod.ReturnType != typeof(void))
            {
                Type returnType = invocation.GetClosedParameterType(callbackMethod.ReturnType);
                returnValue = invokeMethodOnTarget.CodeBuilder.DeclareLocal(returnType);
                invokeMethodOnTarget.CodeBuilder.AddStatement(new AssignStatement(returnValue, methodOnTargetInvocationExpression));
            }
            else
            {
                invokeMethodOnTarget.CodeBuilder.AddStatement(new ExpressionStatement(methodOnTargetInvocationExpression));
            }

            foreach (KeyValuePair <int, LocalReference> byRefArgument in byRefArguments)
            {
                int            index          = byRefArgument.Key;
                LocalReference localReference = byRefArgument.Value;
                invokeMethodOnTarget.CodeBuilder.AddStatement(
                    new ExpressionStatement(
                        new MethodInvocationExpression(SelfReference.Self,
                                                       InvocationMethods.SetArgumentValue,
                                                       new LiteralIntExpression(index),
                                                       new ConvertExpression(typeof(object),
                                                                             localReference.
                                                                             Type,
                                                                             new ReferenceExpression
                                                                                 (localReference)))
                        ));
            }

            if (callbackMethod.ReturnType != typeof(void))
            {
                var setRetVal =
                    new MethodInvocationExpression(SelfReference.Self,
                                                   InvocationMethods.SetReturnValue,
                                                   new ConvertExpression(typeof(object), returnValue.Type, returnValue.ToExpression()));

                invokeMethodOnTarget.CodeBuilder.AddStatement(new ExpressionStatement(setRetVal));
            }

            invokeMethodOnTarget.CodeBuilder.AddStatement(new ReturnStatement());
        }