protected abstract TProxyGenerator CreateProxyGenerator()

in src/Microsoft.ServiceFabric.Services.Remoting/V2/Builder/ProxyGeneratorBuilder.cs [215:308]


        protected abstract TProxyGenerator CreateProxyGenerator(
            Type proxyInterfaceType,
            Type proxyActivatorType);

        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 = 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<IServiceRemotingResponseMessageBody>));

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