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); }
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); } }