예제 #1
0
        private void AddVoidMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceDescriptionId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes,
            string interfaceName)
        {
            var interfaceMethod = methodDescription.MethodInfo;

            var methodBuilder = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder(
                classBuilder,
                interfaceMethod);

            var ilGen = methodBuilder.GetILGenerator();

            // Create Wrapped Request
            LocalBuilder wrappedRequestBody =
                CreateWrappedRequestBody(methodDescription, methodBodyTypes, ilGen, methodDescription.MethodInfo.GetParameters());

            this.AddVoidMethodImplementation(
                ilGen,
                interfaceDescriptionId,
                methodDescription,
                wrappedRequestBody,
                interfaceName);

            ilGen.Emit(OpCodes.Ret);
        }
예제 #2
0
        internal static LocalBuilder CreateWrappedRequestBody(
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes,
            ILGenerator ilGen,
            ParameterInfo[] parameters)
        {
            var parameterLength = parameters.Length;

            if (methodDescription.HasCancellationToken)
            {
                // Cancellation token is tracked locally and should not be serialized and sent
                // as a part of the request body.
                parameterLength -= 1;
            }

            if (parameterLength == 0)
            {
                return(null);
            }

            LocalBuilder wrappedRequestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType);
            var          requestBodyCtor    = methodBodyTypes.RequestBodyType.GetConstructor(Type.EmptyTypes);

            if (requestBodyCtor != null)
            {
                ilGen.Emit(OpCodes.Newobj, requestBodyCtor);
                ilGen.Emit(OpCodes.Stloc, wrappedRequestBody);

                var argsLength = parameters.Length;
                if (methodDescription.HasCancellationToken)
                {
                    // Cancellation token is tracked locally and should not be serialized and sent
                    // as a part of the request body.
                    argsLength -= 1;
                }

                for (var i = 0; i < argsLength; i++)
                {
                    ilGen.Emit(OpCodes.Ldloc, wrappedRequestBody);
                    ilGen.Emit(OpCodes.Ldarg, i + 1);
                    ilGen.Emit(OpCodes.Stfld, methodBodyTypes.RequestBodyType.GetField(parameters[i].Name));
                }
            }

            return(wrappedRequestBody);
        }
예제 #3
0
        private static void AddIfWrapMsgGetParameters(
            ILGenerator ilGen,
            LocalBuilder castedObject,
            MethodBodyTypes methodBodyTypes)
        {
            LocalBuilder wrappedRequest = null;

            wrappedRequest = ilGen.DeclareLocal(typeof(object));

            var getValueMethod = typeof(WrappedMessage).GetProperty("Value").GetGetMethod();

            ilGen.Emit(OpCodes.Ldarg_3); // request object
            ilGen.Emit(OpCodes.Callvirt, getValueMethod);
            ilGen.Emit(OpCodes.Stloc, wrappedRequest);

            // then cast and  call GetField
            LocalBuilder castedRequestBody = null;

            if (methodBodyTypes.RequestBodyType != null)
            {
                // cast the request body
                // var castedRequestBody = (<RequestBodyType>)requestBody;
                castedRequestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType);
                ilGen.Emit(OpCodes.Ldloc, wrappedRequest); // wrapped request
                ilGen.Emit(OpCodes.Castclass, methodBodyTypes.RequestBodyType);
                ilGen.Emit(OpCodes.Stloc, castedRequestBody);
            }

            // now invoke the method on the casted object
            ilGen.Emit(OpCodes.Ldloc, castedObject);

            if (methodBodyTypes.RequestBodyType != null)
            {
                foreach (var field in methodBodyTypes.RequestBodyType.GetFields())
                {
                    // ReSharper disable once AssignNullToNotNullAttribute
                    // castedRequestBody is set to non-null in the previous if check on the same condition
                    ilGen.Emit(OpCodes.Ldloc, castedRequestBody);
                    ilGen.Emit(OpCodes.Ldfld, field);
                }
            }
        }
예제 #4
0
        private void AddIfMethodIdInvokeBlock(
            ILGenerator ilGen,
            Label elseLabel,
            LocalBuilder castedObject,
            MethodDescription methodDescription,
            string interfaceName,
            MethodBodyTypes methodBodyTypes)
        {
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);
            ilGen.Emit(OpCodes.Bne_Un, elseLabel);

            // Check If its Wrapped , then call getparam
            var requestBody = typeof(IActorRequestMessageBody);

            // now invoke the method on the casted object
            ilGen.Emit(OpCodes.Ldloc, castedObject);

            // Check if its WrappedMessage
            var elseLabelforWrapped = ilGen.DefineLabel();

            this.AddACheckIfItsWrappedMessage(ilGen, elseLabelforWrapped);
            var endlabel = ilGen.DefineLabel();

            // 2 If true then call GetValue
            AddIfWrapMsgGetParameters(ilGen, castedObject, methodBodyTypes);
            ilGen.Emit(OpCodes.Br, endlabel);
            ilGen.MarkLabel(elseLabelforWrapped);

            // else call GetParameter on IServiceRemotingMessageBody
            AddIfNotWrapMsgGetParameter(ilGen, castedObject, methodDescription, requestBody);

            ilGen.MarkLabel(endlabel);

            ilGen.EmitCall(OpCodes.Callvirt, methodDescription.MethodInfo, null);
            ilGen.Emit(OpCodes.Ret);
        }
예제 #5
0
        private static MethodBodyTypes Build(
            ICodeBuilderNames codeBuilderNames,
            CodeBuilderContext context,
            MethodDescription methodDescription)
        {
            var methodDataTypes = new MethodBodyTypes()
            {
                RequestBodyType              = null,
                ResponseBodyType             = null,
                HasCancellationTokenArgument = methodDescription.HasCancellationToken,
            };

            if ((methodDescription.Arguments != null) && (methodDescription.Arguments.Length != 0))
            {
                methodDataTypes.RequestBodyType = BuildRequestBodyType(codeBuilderNames, context, methodDescription);
            }

            if (TypeUtility.IsTaskType(methodDescription.ReturnType) && methodDescription.ReturnType.GetTypeInfo().IsGenericType)
            {
                methodDataTypes.ResponseBodyType = BuildResponseBodyType(codeBuilderNames, context, methodDescription);
            }

            return(methodDataTypes);
        }
        private void AddIfMethodIdInvokeAsyncBlock(
            ILGenerator ilGen,
            Label elseLabel,
            LocalBuilder castedObject,
            MethodDescription methodDescription,
            string interfaceName,
            MethodBodyTypes methodBodyTypes)
        {
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);
            ilGen.Emit(OpCodes.Bne_Un, elseLabel);

            var invokeTask  = ilGen.DeclareLocal(methodDescription.ReturnType);
            var requestBody = typeof(IActorRequestMessageBody);

            // now invoke the method on the casted object
            ilGen.Emit(OpCodes.Ldloc, castedObject);

            // Check if its WrappedMessage
            var elseLabelforWrapped = ilGen.DefineLabel();

            this.AddACheckIfItsWrappedMessage(ilGen, elseLabelforWrapped);
            var endlabel = ilGen.DefineLabel();

            // 2 If true then call GetValue
            AddIfWrapMsgGetParameters(ilGen, castedObject, methodBodyTypes);
            ilGen.Emit(OpCodes.Br, endlabel);
            ilGen.MarkLabel(elseLabelforWrapped);

            // else call GetParameter on IServiceRemotingMessageBody
            AddIfNotWrapMsgGetParameter(ilGen, castedObject, methodDescription, requestBody);

            ilGen.MarkLabel(endlabel);

            if (methodDescription.HasCancellationToken)
            {
                ilGen.Emit(OpCodes.Ldarg, 5);
            }

            ilGen.EmitCall(OpCodes.Callvirt, methodDescription.MethodInfo, null);
            ilGen.Emit(OpCodes.Stloc, invokeTask);

            // call the base method to return continuation task
            if (TypeUtility.IsTaskType(methodDescription.ReturnType) &&
                methodDescription.ReturnType.GetTypeInfo().IsGenericType)
            {
                // the return is Task<IServiceRemotingMessageBody>
                var continueWithGenericMethodInfo =
                    this.continueWithResultMethodInfo.MakeGenericMethod(methodDescription.ReturnType
                                                                        .GenericTypeArguments[0]);

                ilGen.Emit(OpCodes.Ldarg_0); // base
                ilGen.Emit(OpCodes.Ldstr, interfaceName);
                ilGen.Emit(OpCodes.Ldstr, methodDescription.Name);
                ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);
                ilGen.Emit(OpCodes.Ldarg, 4); // message body factory
                ilGen.Emit(OpCodes.Ldloc, invokeTask);
                ilGen.EmitCall(OpCodes.Call, continueWithGenericMethodInfo, null);
                ilGen.Emit(OpCodes.Ret);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldarg_0); // base
                ilGen.Emit(OpCodes.Ldloc, invokeTask);
                ilGen.EmitCall(OpCodes.Call, this.continueWithMethodInfo, null);
                ilGen.Emit(OpCodes.Ret);
            }
        }
예제 #7
0
        private void AddAsyncMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes,
            string interfaceName)
        {
            var interfaceMethod = methodDescription.MethodInfo;
            var parameters      = interfaceMethod.GetParameters();
            var methodBuilder   = CodeBuilderUtils.CreateExplitInterfaceMethodBuilder(
                classBuilder,
                interfaceMethod);
            var ilGen           = methodBuilder.GetILGenerator();
            var parameterLength = parameters.Length;

            if (methodDescription.HasCancellationToken)
            {
                // Cancellation token is tracked locally and should not be serialized and sent
                // as a part of the request body.
                parameterLength -= 1;
            }

            LocalBuilder requestMessage = null;

            if (parameterLength > 0)
            {
                // Create Wrapped Message
                // create requestBody and assign the values to its field from the arguments
                var wrappedRequestBody = CreateWrappedRequestBody(methodDescription, methodBodyTypes, ilGen, parameters);

                // create IServiceRemotingRequestMessageBody message
                requestMessage = this.CreateRequestRemotingMessageBody(methodDescription, interfaceName, ilGen, parameterLength, wrappedRequestBody);

                // Check if requestMessage is not implementing WrappedMessage , then call SetParam
                this.SetParameterIfNeeded(ilGen, requestMessage, parameterLength, parameters);
            }

            var objectTask = ilGen.DeclareLocal(typeof(Task <IActorResponseMessageBody>));

            // call the base InvokeMethodAsync method
            ilGen.Emit(OpCodes.Ldarg_0);                       // base
            ilGen.Emit(OpCodes.Ldc_I4, interfaceId);           // interfaceId
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);  // methodId
            ilGen.Emit(OpCodes.Ldstr, methodDescription.Name); // method name

            if (requestMessage != null)
            {
                ilGen.Emit(OpCodes.Ldloc, requestMessage);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldnull);
            }

            // Cancellation token argument
            if (methodDescription.HasCancellationToken)
            {
                // Last argument should be the cancellation token
                var cancellationTokenArgIndex = parameters.Length;
                ilGen.Emit(OpCodes.Ldarg, cancellationTokenArgIndex);
            }
            else
            {
                var cancellationTokenNone = typeof(CancellationToken).GetMethod("get_None");
                ilGen.EmitCall(OpCodes.Call, cancellationTokenNone, null);
            }

            ilGen.EmitCall(OpCodes.Call, this.invokeAsyncMethodInfo, null);
            ilGen.Emit(OpCodes.Stloc, objectTask);

            // call the base method to get the continuation task and
            // convert the response body to return value when the task is finished
            if (TypeUtility.IsTaskType(methodDescription.ReturnType) &&
                methodDescription.ReturnType.GetTypeInfo().IsGenericType)
            {
                var retvalType = methodDescription.ReturnType.GetGenericArguments()[0];

                ilGen.Emit(OpCodes.Ldarg_0);                      // base pointer
                ilGen.Emit(OpCodes.Ldc_I4, interfaceId);          // interfaceId
                ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId
                ilGen.Emit(OpCodes.Ldloc, objectTask);            // task<IServiceRemotingResponseMessageBody>
                ilGen.Emit(OpCodes.Call, this.continueWithResultMethodInfo.MakeGenericMethod(retvalType));
                ilGen.Emit(OpCodes.Ret);                          // return base.ContinueWithResult<TResult>(task);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldarg_0);           // base pointer
                ilGen.Emit(OpCodes.Ldloc, objectTask); // task<object>
                ilGen.Emit(OpCodes.Call, this.continueWithMethodInfo);
                ilGen.Emit(OpCodes.Ret);               // return base.ContinueWith(task);
            }
        }