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