DeftTech.DuckTyping.DelegateDuckProxyType.ImplementInvokeMethod C# (CSharp) Method

ImplementInvokeMethod() private method

Implements the method of the proxy type that invokes the delegate given in its constructor.
private ImplementInvokeMethod ( TypeBuilder proxyType, FieldInfo duckDelegateField ) : MethodBuilder
proxyType System.Reflection.Emit.TypeBuilder Type builder to define the invoke method in.
duckDelegateField System.Reflection.FieldInfo Field that stores a reference to the delegate to call.
return System.Reflection.Emit.MethodBuilder
        private MethodBuilder ImplementInvokeMethod(TypeBuilder proxyType, FieldInfo duckDelegateField)
        {
            MethodInfo variantMethod = m_ToDelegateType.GetMethod("Invoke");
            MethodInfo duckMethod = m_FromDelegateType.GetMethod("Invoke");

            ParameterInfo[] variantMethodParameters = variantMethod.GetParameters();
            ParameterInfo[] duckMethodParameters = duckMethod.GetParameters();

            MethodBuilder proxyMethod = proxyType.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.HideBySig, CallingConventions.HasThis, variantMethod.ReturnType, GetParameterTypes(variantMethodParameters));
            ILGenerator proxyMethodIL = proxyMethod.GetILGenerator();

            // Emit IL to load the proxy instance, then load the value of its duck delegate field
            proxyMethodIL.Emit(OpCodes.Ldarg_0);
            proxyMethodIL.Emit(OpCodes.Ldfld, duckDelegateField);

            // Emit IL to load method arguments
            for (int i = 0; i < variantMethodParameters.Length; i++)
            {
                // Emit IL to load the argument
                proxyMethodIL.Emit(OpCodes.Ldarg, i + 1);

                // Emit IL to cast the argument if necessary
                DuckTyping.EmitCastIL(proxyMethodIL, duckMethodParameters[i].ParameterType, variantMethodParameters[i].ParameterType);
            }

            // Emit IL to call the delegate
            proxyMethodIL.Emit(OpCodes.Callvirt, duckMethod);

            // If we are returning something...
            if (duckMethod.ReturnType != typeof(void))
            {
                // Emit IL to cast the return value if necessary
                DuckTyping.EmitCastIL(proxyMethodIL, variantMethod.ReturnType, duckMethod.ReturnType);
            }

            // Emit IL to return.
            proxyMethodIL.Emit(OpCodes.Ret);

            return proxyMethod;
        }