예제 #1
0
    /// <summary>
    /// Write a DynamicMethod call by creating and injecting a custom delegate in the proxyType
    /// </summary>
    /// <param name="il">LazyILGenerator instance</param>
    /// <param name="dynamicMethod">Dynamic method to get called</param>
    /// <param name="proxyType">ProxyType builder</param>
    internal static void WriteDynamicMethodCall(this LazyILGenerator il, DynamicMethod dynamicMethod, TypeBuilder proxyType)
    {
        // We create a custom delegate inside the module builder
        CreateDelegateTypeFor(proxyType, dynamicMethod, out Type delegateType, out MethodInfo invokeMethod);
        int index;

        lock (_dynamicMethods)
        {
            _dynamicMethods.Add(dynamicMethod);
            index = _dynamicMethods.Count - 1;
        }

        // We fill the DelegateCache<> for that custom type with the delegate instance
        MethodInfo fillDelegateMethodInfo = typeof(DuckType.DelegateCache <>).MakeGenericType(delegateType).GetMethod("FillDelegate", BindingFlags.NonPublic | BindingFlags.Static);

        fillDelegateMethodInfo.Invoke(null, new object[] { index });

        // We get the delegate instance and load it in to the stack before the parameters (at the begining of the IL body)
        il.SetOffset(0);
        il.EmitCall(OpCodes.Call, typeof(DuckType.DelegateCache <>).MakeGenericType(delegateType).GetMethod("GetDelegate"), null);
        il.ResetOffset();

        // We emit the call to the delegate invoke method.
        il.EmitCall(OpCodes.Callvirt, invokeMethod, null);
    }