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