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