in src/Microsoft.ServiceFabric.Services.Remoting/Builder/ProxyGeneratorBuilder.cs [126:222]
protected virtual 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);
}
}