private void AddVoidMethodImplementationV1(
     ILGenerator ilGen,
     int interfaceId,
     MethodDescription methodDescription,
     MethodBodyTypes methodBodyTypes)
 {
 }
コード例 #2
0
        private void AddVoidMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes)
        {
            var interfaceMethod = methodDescription.MethodInfo;
            var parameters      = interfaceMethod.GetParameters();

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

            var ilGen = methodBuilder.GetILGenerator();

            LocalBuilder requestBody = null;

            if (methodBodyTypes.RequestBodyType != null)
            {
                // create requestBody and assign the values to its field from the arguments
                requestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType);
                var requestBodyCtor = methodBodyTypes.RequestBodyType.GetConstructor(Type.EmptyTypes);

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

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

            // call the base Invoke method
            ilGen.Emit(OpCodes.Ldarg_0);                      // base
            ilGen.Emit(OpCodes.Ldc_I4, interfaceId);          // interfaceId
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId

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

            ilGen.EmitCall(OpCodes.Call, this.invokeMethodInfo, null);
            ilGen.Emit(OpCodes.Ret);
        }
コード例 #3
0
        private void AddAsyncMethodImplementation(
            TypeBuilder classBuilder,
            int interfaceId,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes)
        {
            var interfaceMethod = methodDescription.MethodInfo;
            var parameters      = interfaceMethod.GetParameters();

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

            var ilGen = methodBuilder.GetILGenerator();

            LocalBuilder requestBody = null;

            if (methodBodyTypes.RequestBodyType != null)
            {
                // create requestBody and assign the values to its field from the arguments
                requestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType);
                var requestBodyCtor = methodBodyTypes.RequestBodyType.GetConstructor(Type.EmptyTypes);

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

                    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 = argsLength - 1;
                    }

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

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

            // call the base InvokeAsync method
            ilGen.Emit(OpCodes.Ldarg_0);                      // base
            ilGen.Emit(OpCodes.Ldc_I4, interfaceId);          // interfaceId
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id); // methodId

            if (requestBody != null)
            {
                ilGen.Emit(OpCodes.Ldloc, requestBody);
            }
            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 (methodBodyTypes.ResponseBodyType != null)
            {
                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<object>
                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);
            }
        }
        private void AddIfMethodIdInvokeAsyncBlock(
            ILGenerator ilGen,
            Label elseLabel,
            LocalBuilder castedObject,
            MethodDescription methodDescription,
            MethodBodyTypes methodBodyTypes)
        {
            ilGen.Emit(OpCodes.Ldarg_1);
            ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);
            ilGen.Emit(OpCodes.Bne_Un_S, elseLabel);

            var invokeTask = ilGen.DeclareLocal(methodDescription.ReturnType);

            LocalBuilder castedRequestBody = null;

            if (methodBodyTypes.RequestBodyType != null)
            {
                // cast the request body
                // var castedRequestBody = (<RequestBodyType>)requestBody;
                castedRequestBody = ilGen.DeclareLocal(methodBodyTypes.RequestBodyType);
                ilGen.Emit(OpCodes.Ldarg_3);
                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);
                }
            }

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

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

            // call the base method to return continuation task
            if (methodBodyTypes.ResponseBodyType != null)
            {
                // the return is Task<T>
                var continueWithGenericMethodInfo = this.continueWithResultMethodInfo.MakeGenericMethod(
                    methodDescription.ReturnType.GenericTypeArguments[0]);

                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldc_I4, methodDescription.Id);
                ilGen.Emit(OpCodes.Ldloc, invokeTask);
                ilGen.EmitCall(OpCodes.Call, continueWithGenericMethodInfo, null);
                ilGen.Emit(OpCodes.Ret);
            }
            else
            {
                ilGen.Emit(OpCodes.Ldarg_0);
                ilGen.Emit(OpCodes.Ldloc, invokeTask);
                ilGen.EmitCall(OpCodes.Call, this.continueWithMethodInfo, null);
                ilGen.Emit(OpCodes.Ret);
            }
        }