private void ImplementBody(MethodDefinition method, ILProcessor il, FieldDefinition attributeField, FieldDefinition methodInfoField, MethodInterceptorBuilder builder) { // We want to call the interceptor's setter method: // Task<object> InvokeMethodAsync(MethodInfo methodInfo, object instance, object[] parameters, Func<object[], Task<object>> invoker) // Get interceptor attribute il.LoadField(attributeField); // Leave MethodInfo on the stack as the first argument il.LoadField(methodInfoField); // Leave the instance on the stack as the second argument EmitInstanceArgument(il, method); // Colllect all the parameters into a single array as the third argument ComposeArgumentsIntoArray(il, method); // Leave the delegate for the proceed implementation on the stack as the fourth argument builder.EmitProceedStruct(il); il.EmitDelegate(builder.ProceedReference, Context.Func2Type, Context.ObjectArrayType, Context.TaskTType.MakeGenericInstanceType(TypeSystem.ObjectReference)); // Finally, we emit the call to the interceptor il.Emit(OpCodes.Callvirt, baseInvoke); // Before we return, we need to convert the `Task<object>` to `Task<T>` We use the // AsyncInvoker helper so we don't have to build the state machine from scratch. var unwrappedReturnType = ((GenericInstanceType)method.ReturnType).GenericArguments[0]; var typedInvoke = asyncInvokerUnwrap.MakeGenericMethod(unwrappedReturnType); il.Emit(OpCodes.Call, typedInvoke); // Return il.Emit(OpCodes.Ret); }
private void ImplementBody(MethodDefinition method, ILProcessor il, FieldDefinition attributeField, FieldDefinition methodInfoField, MethodInterceptorBuilder builder) { // We want to call the interceptor's setter method: // object InvokeMethod(MethodInfo methodInfo, object instance, object[] parameters, Func<object[], object> invoker) // Get interceptor attribute il.LoadField(attributeField); // Leave MethodInfo on the stack as the first argument il.LoadField(methodInfoField); // Leave the instance on the stack as the second argument EmitInstanceArgument(il, method); // Colllect all the parameters into a single array as the third argument ComposeArgumentsIntoArray(il, method); // Leave the delegate for the proceed implementation on the stack as the fourth argument builder.EmitProceedStruct(il); il.EmitDelegate(builder.ProceedReference, Context.Func2Type, Context.ObjectArrayType, TypeSystem.ObjectReference); // Finally, we emit the call to the interceptor il.Emit(OpCodes.Callvirt, baseInvoke); if (method.ReturnType.CompareTo(TypeSystem.VoidReference)) { il.Emit(OpCodes.Pop); } else { // Now unbox the value if necessary il.EmitUnboxIfNeeded(method.ReturnType, method.DeclaringType); } // Return il.Emit(OpCodes.Ret); }