public static Delegate CreateDynamicMethod(Type delegateType, Action <ILGenerator> ilGen)
        {
            var invokeMethod   = delegateType.GetMethod("Invoke");
            var returnType     = invokeMethod.ReturnType;
            var parameterTypes = invokeMethod.GetParameters().Select(p => p.ParameterType).ToArray();

#if SILVERLIGHT
            var method = CreateDynamicMethodWithVisibilityChecks(returnType, parameterTypes, ilGen);
            return(Delegate.CreateDelegate(delegateType, method));
#else
            // If you try to call the DynamicMethod constructor specifying a ByRef type
            // as the return value it throws NotSupportedException with the following message:
            // "The return Type contains some invalid type(i.e. null, ByRef)". In order to make
            // it working we are applying the following simple workaround:
            //   1. Pass a non-ref type to constructor and create dynamic method instance
            //   2. Using reflection change the value of private field 'm_returnType' of the
            //      newly created dynamic method to be ByRef type
            Type dynamicReturnType = (returnType.IsByRef) ? returnType.GetElementType() : returnType;

            var method = new DynamicMethod("DynamicMethod_" + Guid.NewGuid().ToString("N"), dynamicReturnType, parameterTypes, true);

            if (returnType.IsByRef)
            {
                method.GetType().GetField("m_returnType", BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
                .SetValue(method, returnType);
            }

            ilGen(method.GetILGenerator());
            return(method.CreateDelegate(delegateType));
#endif
        }
示例#2
0
        public static RefGetter <T, U> create_refgetter <T, U>(string s_field, BindingFlags bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.DeclaredOnly)
        {
            const BindingFlags bf = BindingFlags.NonPublic |
                                    BindingFlags.Instance |
                                    BindingFlags.DeclaredOnly;

            var fi = typeof(T).GetField(s_field, bindingFlags);

            if (fi == null)
            {
                throw new MissingFieldException(typeof(T).Name, s_field);
            }

            var s_name = "__refget_" + typeof(T).Name + "_fi_" + fi.Name;

            // workaround for using ref-return with DynamicMethod:
            //   a.) initialize with dummy return value
            var dm = new DynamicMethod(s_name, typeof(U), new[] { typeof(T) }, typeof(T), true);

            //   b.) replace with desired 'ByRef' return value
            dm.GetType().GetField("m_returnType", bf).SetValue(dm, typeof(U).MakeByRefType());

            var il = dm.GetILGenerator();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Ldflda, fi);
            il.Emit(OpCodes.Ret);

            return((RefGetter <T, U>)dm.CreateDelegate(typeof(RefGetter <T, U>)));
        }
        public static IntPtr PrepareMethod(this DynamicMethod meth)
        {
            Type t = meth.GetType();
            RuntimeMethodHandle handle =
                t.GetMethod("GetMethodDescriptor", mflag0) is MethodInfo getmd
                    ? (RuntimeMethodHandle)getmd.Invoke(meth, null)
                    : t.GetField("m_method", mflag0) is FieldInfo mm
                    ? (RuntimeMethodHandle)mm.GetValue(meth)
                    : (RuntimeMethodHandle)t.GetField("mhandle", mflag0).GetValue(meth);

            Type ht = handle.GetType();

            object result =
                ht.GetField("m_value", mflag0) is FieldInfo fd
                ? fd.GetValue(handle)
                : ht.GetMethod("GetMethodInfo", mflag0) is MethodInfo mi
                ? mi.Invoke(handle, null)
                : null;

            if (result != null)
            {
                try
                {
                    // 2020 01 30
                    // dynamicmethod 코드에 전혀 문제가 없는 경우에
                    // 여기서 오류가 발생하지 않는다
                    m_compileMeth.Invoke(null, new object[1] {
                        result
                    });
                    return(handle.GetFunctionPointer());
                }
            }
        /// <summary>
        /// Create a pointer for static field <paramref name="s_field"/>
        /// </summary>
        /// <typeparam name="U"></typeparam>
        /// <param name="s_field"></param>
        /// <returns> Pointer to <paramref name="s_field"/></returns>
        /// <remarks> Source: https://stackoverflow.com/a/45046664/13073994 </remarks>
        public static RefGetter <U> CreateStaticFieldRef <U>(Type type, String s_field)
        {
            const BindingFlags bf = BindingFlags.NonPublic |
                                    BindingFlags.Static |
                                    BindingFlags.DeclaredOnly;

            var fi = type.GetField(s_field, bf);

            if (fi == null)
            {
                throw new MissingFieldException(type.Name, s_field);
            }

            var s_name = "__refget_" + type.Name + "_fi_" + fi.Name;

            // workaround for using ref-return with DynamicMethod:
            //   a.) initialize with dummy return value
            var dm = new DynamicMethod(s_name, typeof(U), null, type, true);

            //   b.) replace with desired 'ByRef' return value
            dm.GetType().GetField("returnType", AccessTools.all).SetValue(dm, typeof(U).MakeByRefType());

            var il = dm.GetILGenerator();

            il.Emit(OpCodes.Ldsflda, fi);
            il.Emit(OpCodes.Ret);

            return((RefGetter <U>)dm.CreateDelegate(typeof(RefGetter <U>)));
        }
示例#5
0
        public void RtDynamicMethod()
        {
            var module = ModuleDefinition.FromFile(typeof(TDynamicMethod).Assembly.Location);

            DynamicMethod generateDynamicMethod = TDynamicMethod.GenerateDynamicMethod();

            var rtDynamicMethod = generateDynamicMethod.GetType().GetField("m_dynMethod", (BindingFlags)(-1))?.GetValue(generateDynamicMethod);

            var dynamicMethodDefinition = new DynamicMethodDefinition(module, rtDynamicMethod);

            Assert.NotNull(dynamicMethodDefinition);

            Assert.NotEmpty(dynamicMethodDefinition.CilMethodBody.Instructions);

            Assert.Equal(dynamicMethodDefinition.CilMethodBody.Instructions.Select(q => q.OpCode), new []
            {
                CilOpCodes.Ldarg_0,
                CilOpCodes.Call,
                CilOpCodes.Ldarg_1,
                CilOpCodes.Ret
            });
            Assert.Equal(dynamicMethodDefinition.Parameters.Select(q => q.ParameterType), new TypeSignature[]
            {
                module.CorLibTypeFactory.String,
                module.CorLibTypeFactory.Int32
            });
        }
示例#6
0
        private static IntPtr GetDynamicMethodAddress(DynamicMethod dynamicMethod)
        {
            var type      = dynamicMethod.GetType();
            var fieldInfo = type.GetField("m_method", BindingFlags.Instance | BindingFlags.NonPublic);

            if (fieldInfo == null)
            {
                fieldInfo = type.GetField("m_methodHandle", BindingFlags.Instance | BindingFlags.NonPublic);
            }
            var runtimeMethodInfoStub = fieldInfo?.GetValue(dynamicMethod);

            if (runtimeMethodInfoStub == null)
            {
                return(IntPtr.Zero);
            }
            var runtimeMethodHandleInternal = runtimeMethodInfoStub.GetType().GetField("m_value", BindingFlags.Instance | BindingFlags.Public).GetValue(runtimeMethodInfoStub);
            var getFunctionPointer          = typeof(RuntimeMethodHandle).GetMethod(nameof(RuntimeMethodHandle.GetFunctionPointer), BindingFlags.Static | BindingFlags.NonPublic);
            var ptr = (IntPtr)getFunctionPointer.Invoke(null, new[] { runtimeMethodHandleInternal });

            return(ptr);
        }
示例#7
0
        public static IntPtr PrepareMethod(this DynamicMethod meth)
        {
            Type t = meth.GetType();

            // mono only
            MethodInfo mi = t.GetMethod("CreateDynMethod", mflag0);

            if (mi != null)
            {
                mi.Invoke(meth, null);
                return(((RuntimeMethodHandle)t.GetField("mhandle", mflag0).GetValue(meth)).GetFunctionPointer());
            }

            RuntimeMethodHandle handle;
            FieldInfo           fi;

            mi = t.GetMethod("GetMethodDescriptor", mflag0);
            if (mi != null)
            {
                handle = (RuntimeMethodHandle)mi.Invoke(meth, null);
            }
            else
            {
                fi     = t.GetField("m_method", mflag0);
                handle =
                    fi != null
                    ? (RuntimeMethodHandle)fi.GetValue(meth)
                    : default;
            }

            t = handle.GetType();

            object result;

            fi = t.GetField("m_value", mflag0);
            if (fi != null)
            {
                result = fi.GetValue(handle);
            }
            else
            {
                fi = t.GetField("Value", mflag0);
                if (fi != null)
                {
                    result = fi.GetValue(handle);
                }
                else
                {
                    mi = t.GetMethod("GetMethodInfo", mflag0);
                    if (mi != null)
                    {
                        result = mi.Invoke(handle, null);
                    }
                    else
                    {
                        result = null;
                    }
                }
            }

            if (result != null)
            {
                try
                {
                    // 2020 01 30
                    // dynamicmethod 코드에 전혀 문제가 없는 경우에
                    // 여기서 오류가 발생하지 않는다
                    m_compileMeth.Invoke(null, new object[1] {
                        result
                    });
                    return(handle.GetFunctionPointer());
                }
            }
示例#8
0
        internal static void PrepareDynamicMethod(DynamicMethod method)
        {
            var nonPublicInstance = BindingFlags.NonPublic | BindingFlags.Instance;
            var nonPublicStatic   = BindingFlags.NonPublic | BindingFlags.Static;

            // on mono, just call 'CreateDynMethod'
            //
            var m_CreateDynMethod = method.GetType().GetMethod("CreateDynMethod", nonPublicInstance);

            if (m_CreateDynMethod != null)
            {
                var h_CreateDynMethod = MethodInvoker.GetHandler(m_CreateDynMethod);
                h_CreateDynMethod(method, new object[0]);
                return;
            }

            // on all .NET Core versions, call 'RuntimeHelpers._CompileMethod' but with a different parameter:
            //
            var m__CompileMethod = typeof(RuntimeHelpers).GetMethod("_CompileMethod", nonPublicStatic);
            var h__CompileMethod = MethodInvoker.GetHandler(m__CompileMethod);

            var m_GetMethodDescriptor = method.GetType().GetMethod("GetMethodDescriptor", nonPublicInstance);
            var h_GetMethodDescriptor = MethodInvoker.GetHandler(m_GetMethodDescriptor);
            var handle = (RuntimeMethodHandle)h_GetMethodDescriptor(method, new object[0]);

            // 1) RuntimeHelpers._CompileMethod(handle.GetMethodInfo())
            //
            object runtimeMethodInfo = null;
            var    f_m_value         = handle.GetType().GetField("m_value", nonPublicInstance);

            if (f_m_value != null)
            {
                runtimeMethodInfo = f_m_value.GetValue(handle);
            }
            else
            {
                var m_GetMethodInfo = handle.GetType().GetMethod("GetMethodInfo", nonPublicInstance);
                if (m_GetMethodInfo != null)
                {
                    var h_GetMethodInfo = MethodInvoker.GetHandler(m_GetMethodInfo);
                    runtimeMethodInfo = h_GetMethodInfo(handle, new object[0]);
                }
            }
            if (runtimeMethodInfo != null)
            {
                try
                {
                    // this can throw BadImageFormatException "An attempt was made to load a program with an incorrect format"
                    h__CompileMethod(null, new object[] { runtimeMethodInfo });
                    return;
                }
#pragma warning disable RECS0022
                catch
#pragma warning restore RECS0022
                {
                }
            }

            // 2) RuntimeHelpers._CompileMethod(handle.Value)
            //
            if (m__CompileMethod.GetParameters()[0].ParameterType.IsAssignableFrom(handle.Value.GetType()))
            {
                h__CompileMethod(null, new object[] { handle.Value });
                return;
            }

            // 3) RuntimeHelpers._CompileMethod(handle)
            //
            if (m__CompileMethod.GetParameters()[0].ParameterType.IsAssignableFrom(handle.GetType()))
            {
                h__CompileMethod(null, new object[] { handle });
                return;
            }
        }