.net - 当属性类型为 Int64 时,DynamicMethod 返回错误值

标签 .net reflection reflection.emit

我正在编写一个例程,以使用 DynamicMethod 从对象中检索值。它适用于大多数数据类型,但 DateTime.Ticks 除外,它是 int64

在下面的测试应用程序中。我同时使用 MethodInfo 和 DynamicMethod,methodInfo 返回正确的值,但 DynamicMethod 不返回。有什么想法吗?

using System;
using System.Reflection;
using System.Reflection.Emit;

namespace ConsoleApplication2
{
    public delegate object MemberGetDelegate(object obj);

    class Program
    {
        static void Main(string[] args)
        {
            DateTime dat = DateTime.Today;
            PropertyInfo pi = typeof(DateTime).GetProperty("Ticks");
            MethodInfo mi = pi.GetGetMethod();
            Type type = pi.PropertyType;
            object ticks = mi.Invoke(dat, new object[] { });
            Console.WriteLine("Get by MethodInfo " + ticks.ToString());

            MemberGetDelegate mget=TypeUtils.GetMemberFunc(pi);
            object ret = mget(dat);
            Console.WriteLine("Get by DynamicMethod " + ret.ToString());

            Console.Read();
        }
    }

    static class TypeUtils
    {
        public static readonly Type objectType = typeof(object);
        public static readonly Type[] typeArray = new[] { typeof(object) };

        public static MemberGetDelegate GetMemberFunc(PropertyInfo pi)
        {

            MethodInfo mi = pi.GetGetMethod();

            if (mi != null)
            {
                DynamicMethod dm = new DynamicMethod("_" + mi.Name,
                                                     objectType,
                                                     typeArray,
                                                     pi.Module, true);
                ILGenerator il = dm.GetILGenerator();

                // Load the instance of the object (argument 0) onto the stack
                il.Emit(OpCodes.Ldarg_0);

                // Call underlying get method
                il.EmitCall(OpCodes.Callvirt, mi, null);

                //boxing
                if (pi.PropertyType.IsValueType)
                {
                    il.Emit(OpCodes.Box, pi.PropertyType);                   
                }

                // return the value on the top of the stack
                il.Emit(OpCodes.Ret);

                return  (MemberGetDelegate) dm.CreateDelegate(typeof (MemberGetDelegate));

            }
            return null;
        }
    }
}

最佳答案

您正在生成无效代码。如果您使用 Ilasm 编译生成的 IL

ldarg.0
callvirt instance int64 [mscorlib]System.DateTime::get_Ticks()
box int64
ret

然后对可执行文件运行 PEVerify,它会告诉您该代码无效。 (您不能在这样的值类型方法上使用 callvirt )。工作代码应该如下所示

ldarg.0
unbox [mscorlib]System.DateTime
call instance int64 [mscorlib]System.DateTime::get_Ticks()
box int64
ret

相应地调整您的代码生成,它将返回正确的值。

关于.net - 当属性类型为 Int64 时,DynamicMethod 返回错误值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1354368/

相关文章:

asp.net - 当数据源是 EF 上下文时,使用 Asp.Net MVC 3 的哪种方法

c# - 在网站中使用反射访问 AssemblyInfo.cs 中的信息

c# - 使用反射获取二级属性值

c# - 获取通用抽象类的默认构造函数

c# - 使用 Reflection.Emit 覆盖属性定义

c# - .NET 反射器的最佳反汇编工具?

.net - Entity Framework 通用存储库有什么优势吗?

java - 所有非垃圾收集的对象最终都是静态引用的吗?

c# - 将对象字面量提供给 ILGenerator

c# - 为什么结构中的迭代器可以修改这个?