private void AddVoidMethodImplementationV1( ILGenerator ilGen, int interfaceId, MethodDescription methodDescription, MethodBodyTypes methodBodyTypes) { }
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); } }
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); } }