Странное поведение DateTime ToString в динамически генерируемом MSIL - PullRequest
0 голосов
/ 17 мая 2018

Мне нужно что-то, чтобы динамически создавать методы поиска свойств во время выполнения и выполнять быстро, поэтому я разработал решение, используя Reflection Emit:

public static void Func(string properyName, A obj)
{
    var type = obj.GetType();
    var dynamicMethod = new DynamicMethod("PropertyExtractor", typeof(string), new[] { typeof(A) }, type, true);
    var ilGen = dynamicMethod.GetILGenerator();
    var getMethod = type.GetMethod($"get_{properyName}");
    var property = type.GetProperty(properyName);

    ilGen.Emit(OpCodes.Ldarg_0);
    ilGen.Emit(OpCodes.Castclass, type);
    ilGen.Emit(OpCodes.Callvirt, getMethod);
    var toStringMethod = property.PropertyType.GetMethod("ToString", Type.EmptyTypes);
    ilGen.Emit(OpCodes.Call, toStringMethod);
    ilGen.Emit(OpCodes.Ret);
    var @delegate = (F)dynamicMethod.CreateDelegate(typeof(F));
    var a = @delegate(obj);
}

public delegate string F(A obj); 

public abstract class A 
{ 
    public int Id { get; set; } 
    public string Name { get; set; } 
} 

public class B : A 
{ 
    public DateTime Timestamp { get; set; } 
} 

Вот код для его вызова:

var obj = new B
{
    Id = 1,
    Name = "SomeName",
    Timestamp = DateTime.Today
};

Func("Timestamp", obj);

Это только для тестирования, поэтому в методе с именем Func с параметром типа A и т. Д. Как видите, вы даете ему имя свойства и экземпляра, и он создает делегат для извлечения строкового значения свойства в этом конкретном экземпляре. Все отлично работает, пока не появится DateTime. Я тестирую с DateTime.Now, назначенным свойству, и каждый раз, когда я запускаю функцию, я получаю странные значения, такие как: enter image description here Я попытался поставить IFormatProvider на всякий случай - те же результаты. .NET версия 4.7.1, Заранее спасибо.

1 Ответ

0 голосов
/ 17 мая 2018

Я нашел проблему. DateTime - это тип значения, а ToString требует загрузки адреса в стек оценки, а не значения. Когда я добавил локальную переменную времени и добавил инструкции, чтобы сохранить значение в локальной переменной, а затем загрузить адрес этой переменной, оно было разрешено. Спасибо всем, кто откликнулся.

...