我正在编写一个例程,以使用 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/