2009-08-30 133 views
5

我正在使用DynamicMethod从对象检索值的例程上工作。它适用于大多数数据类型,除了DateTime.Ticks,它是int64当属性类型为Int64时,DynamicMethod返回不正确的值

在以下测试应用程序中。我同时使用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; 
     } 
    } 
} 
+0

您能否以您的结果不正确的方式报告? – 2009-08-30 17:24:45

+0

错误值的示例:获取属性633871872000000000 获取方法信息633871872000000000 获取DynamicMethod 3723350993856077580 – 2009-08-30 17:37:56

+0

感谢Lasse发布您的结果。 我最初认为这是造成拳击,所以我改变了委托人的签名和删除了拳击代码,我没有帮助,我仍然得到不正确的值。 – Tony 2009-08-30 18:27:19

回答

4

您正在生成无效的代码。如果你用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 

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

+0

谢谢,这有帮助。增加了拆箱逻辑,它工作正常。 il.Emit(OpCodes.Ldarg_0); //拆箱值类型 如果(pi.PropertyType.IsValueType) { il.Emit(OpCodes.Unbox,pi.ReflectedType); } il.EmitCall(OpCodes.Callvirt,mi,null);如果(pi.PropertyType.IsValueType) il.Emit(OpCodes.Box,pi.PropertyType); } – Tony 2009-08-31 16:19:37

相关问题