public virtual MethodBuilder CreateMethod(ProxyScope proxyScope, MethodDefinition methodDefinition, MemberInfo member, FieldBuilder memberField, FieldBuilder callerMethodField) { MethodInfo method = methodDefinition.Method; // callback method MethodBuilder callbackMethodBuilder = CreateCallbackMethod(proxyScope, methodDefinition.CallbackMethodDefinition); // invocation type Type invocationType = GetOrCreateInvocationType(proxyScope, methodDefinition, callbackMethodBuilder); // method MethodBuilder methodBuilder = proxyScope.DefineMethod(methodDefinition.Name, methodDefinition.MethodAttributes); methodBuilder.SetReturnType(methodDefinition.ReturnType); // parameters methodBuilder.DefineGenericParameters(methodDefinition.GenericArguments); if (methodDefinition.ParameterDefinitions.Length > 0) { DefineParameters(methodBuilder, methodDefinition); } // attributes DefineAttributes(methodBuilder, methodDefinition); // method body var il = methodBuilder.GetILGenerator(); // locals IInterceptorSelector interceptorSelector = proxyScope.TypeDefinition.Options?.InterceptorSelector; FieldBuilder interceptorSelectorField = null; FieldBuilder interceptorMethodField = null; if (interceptorSelector != null) { interceptorSelectorField = FindConstructorField(proxyScope, ProxyScope.InterceptorSelectorFieldName); interceptorMethodField = proxyScope.DefineField(methodDefinition.InterceptorSelectorFieldName, typeof(IInterceptor[]), FieldAttributes.Private); } var returnType = methodDefinition.ReturnType; Type targetType = methodDefinition.TypeDefinition.TargetType; Type localBuilderType = targetType != null ? targetType : typeof(object); LocalBuilder targetLocalBuilder = il.DeclareLocal(localBuilderType); // target LocalBuilder interceptorsLocalBuilder = il.DeclareLocal(typeof(IInterceptor[])); // interceptors LocalBuilder memberLocalBuilder = il.DeclareLocal(typeof(MemberInfo)); // MemberInfo LocalBuilder callerMethodLocalBuilder = il.DeclareLocal(typeof(MethodInfo)); // proxy method LocalBuilder proxyLocalBuilder = il.DeclareLocal(typeof(object)); // proxy LocalBuilder parametersLocalBuilder = il.DeclareLocal(typeof(object[])); // parameters LocalBuilder invocationLocalBuilder = il.DeclareLocal(invocationType); // invocation LocalBuilder returnValueLocalBuilder = null; if (returnType != typeof(void)) { returnValueLocalBuilder = il.DeclareLocal(returnType); } FieldBuilder interceptorsField = proxyScope.ConstructorFields[0]; if (targetType != null) { FieldBuilder targetField = FindConstructorField(proxyScope, methodDefinition.TypeDefinition.TargetFieldName); EmitHelper.StoreFieldToLocal(il, targetField, targetLocalBuilder); } EmitHelper.StoreFieldToLocal(il, memberField, memberLocalBuilder); EmitHelper.StoreFieldToLocal(il, callerMethodField, callerMethodLocalBuilder); EmitHelper.StoreThisToLocal(il, proxyLocalBuilder); if (interceptorSelector != null) { LocalBuilder isNullLocal = il.DeclareLocal(typeof(bool)); Label isNullLabel = il.DefineLabel(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, interceptorMethodField); il.Emit(OpCodes.Ldnull); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Stloc, isNullLocal); il.Emit(OpCodes.Ldloc, isNullLocal); il.Emit(OpCodes.Brfalse_S, isNullLabel); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, interceptorSelectorField); il.Emit(OpCodes.Ldtoken, member.DeclaringType); il.Emit(OpCodes.Call, Methods.GetTypeFromHandle); il.Emit(OpCodes.Ldloc, callerMethodLocalBuilder); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, interceptorsField); il.Emit(OpCodes.Callvirt, Methods.SelectInterceptorsMethod); il.Emit(OpCodes.Stfld, interceptorMethodField); il.MarkLabel(isNullLabel); EmitHelper.StoreFieldToLocal(il, interceptorMethodField, interceptorsLocalBuilder); } else { EmitHelper.StoreFieldToLocal(il, interceptorsField, interceptorsLocalBuilder); } StoreArgsToArray(il, methodDefinition.ParameterDefinitions, parametersLocalBuilder); EmitHelper.CreateInvocation(il, invocationType, targetLocalBuilder, interceptorsLocalBuilder, memberLocalBuilder, callerMethodLocalBuilder, proxyLocalBuilder, parametersLocalBuilder, invocationLocalBuilder); EmitHelper.CallProceed(il, invocationLocalBuilder); // set ref parameters values after Proceed called SetByRefArgs(il, methodDefinition.ParameterDefinitions, invocationLocalBuilder); EmitReturnValue(il, method, invocationLocalBuilder, returnValueLocalBuilder); if (method.DeclaringType.IsInterface) { proxyScope.DefineMethodOverride(methodBuilder, method); } return(methodBuilder); }