DateTime对象没有从MSIL返回正确的值

本文关键字:返回 MSIL 对象 DateTime | 更新日期: 2023-09-27 18:11:37

我注意到我在MSIL中编写的一些代码以高速获取对象的任意属性,但没有获得DateTime属性的正确值。无论DateTime对象的实际值如何,它总是返回相同的值,例如:Year总是返回1,Millisecond返回88,等等…

LINQPad中的一些代码演示了这一点。获取mc.Inner.Age返回正确的值,mc.Inner.DateOfBirth返回正确的日期时间值,但是试图获取mc.Inner.DateOfBirth的任何特定部分总是返回不正确的值。我已经研究并尝试了一些方法来让它发挥作用,但我没有足够的经验来真正知道在这一点上还可以尝试什么。我不确定我的代码中是否有一些微妙的错误,或者DateTime对象是否有一些特殊的东西导致这种情况发生。

void Main()
{
    var mc = new MyClass();
    mc.FirstName = "Jane";
    mc.LastName = "Doe";
    mc.Inner.DateOfBirth = new DateTime(1960, 2, 13);
    mc.Inner.Age = 54;
    Object obj = mc;    
    obj = this.GetObjectProperty(obj, "Inner");
    obj = this.GetObjectProperty(obj, "DateOfBirth");
    obj = this.GetObjectProperty(obj, "Year");
    obj.Dump();
    obj = mc;
    obj = obj.GetType().GetProperty("Inner").GetValue(obj);
    obj = obj.GetType().GetProperty("DateOfBirth").GetValue(obj);
    obj = obj.GetType().GetProperty("Year").GetValue(obj);
    obj.Dump();
}
private Object GetObjectProperty(Object obj, String property)
{
    var m = obj.GetType().GetMethod("get_" + property, BindingFlags.Public | BindingFlags.Instance | BindingFlags.GetProperty);
    DynamicMethod meth = new DynamicMethod("GetObjectProperty", typeof(Object), new [] { typeof(Object) }, obj.GetType());
    var il = meth.GetILGenerator();
    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Castclass, obj.GetType());
    il.EmitCall(OpCodes.Call, m, null);
    if (m.ReturnType.IsValueType)
        il.Emit(OpCodes.Box, m.ReturnType);
    il.Emit(OpCodes.Ret);
    return ((GetObjectPropertyDelegate)meth.CreateDelegate(typeof(GetObjectPropertyDelegate), obj))();
}
private delegate Object GetObjectPropertyDelegate();
public class MyClass
{
    public MyClass()
    {
        this.Inner = new MyInnerClass();
    }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public MyInnerClass Inner { get; set; }
}
public class MyInnerClass
{
    public DateTime DateOfBirth { get; set; }
    public int Age { get; set; }
}

DateTime对象没有从MSIL返回正确的值

对值类型的调用必须传递一个托管指针作为this参数。这是为了支持在值类型上改变方法。

您正在将对象引用传递给值类型的盒装实例。可能,DateTime.Year的代码正在访问一些随机的内存位。您已经破坏了内存安全。这个IL是无法验证的。我不记得盒装和未盒装的内存布局,但你可能正在读取(部分)方法表或虚函数表或对象头的其他部分。

使用Unbox来获取一个指向盒装实例内容的托管指针。