2015-08-06 2 views
1

Я пробовал весь день получать действительную перегрузку для метода System.Object.Finalizer(). Мне нужно ввести финализатор (если его еще нет) в случайные классы. Сам метод должен работать очень хорошо - по крайней мере, отраженный он выглядит действительным, и я не вижу никаких проблем/ошибок CIL.C#/Cecil Создание перегрузки Finalizer

Это код, который создает перегруженный метод:

destructor = new MethodDefinition("Finalize", 
MethodAttributes.Family | MethodAttributes.HideBySig | MethodAttributes.Virtual | 
MethodAttributes.ReuseSlot, module.Import(typeof (void))); 

baseType.Methods.Add(destructor); 

Все решения, которые я нашел в Интернете (которые все являются весьма устарели, очевидно) только показать, что вы должны установить эти атрибуты - ничего больше.

Это сгенерированный компилятором версия:

.method family hidebysig virtual instance void Finalize() cil managed 
{ 
    .override object::Finalize 
    .maxstack 2 
    L_0000: nop 
    L_0001: nop 
    L_0002: ldarg.0 
    L_0003: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() 
    L_0008: ldarg.0 
    L_0009: ldfld class [App]App.Instancing.InstanceId App.Lab.Wpf.MainWindow::_instance 
    L_000e: call bool [App]App.Spy::UnsetToken(class [mscorlib]System.Type, class [App]App.Instancing.InstanceId) 
    L_0013: pop 
    L_0014: leave.s L_001e 
    L_0016: ldarg.0 
    L_0017: call instance void [mscorlib]System.Object::Finalize() 
    L_001c: nop 
    L_001d: endfinally 
    L_001e: ret 
    .try L_0001 to L_0016 finally handler L_0016 to L_001e 
} 

Следующий код CIL мой сгенерированный код. Самая очевидная ошибка и, вероятно, причина, по которой она не работает, - это отсутствие «.override». Я не могу понять, как я это достигаю. Я пробовал все возможное, и это просто не работает.

.method family hidebysig virtual instance void Finalize() cil managed 
{ 
    .maxstack 8 
    L_0000: ldarg.0 
    L_0001: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() 
    L_0006: ldarg.0 
    L_0007: ldfld class [App]App.Instancing.InstanceId App.Lab.Forms.MainWindow::vbbgsMtrInsVr0221 
    L_000c: call bool [App]App.Spy::UnsetToken(class [mscorlib]System.Type, class [App]App.Instancing.InstanceId) 
    L_0011: pop 
    L_0012: ldarg.0 
    L_0013: call instance void [mscorlib]System.Object::Finalize() 
} 

Как это работает? Когда я переключаюсь на отражение C#, код выглядит отлично. Он даже говорит «protected override Finalize()», но PEVerify указывает «плохие заголовки», и приложение даже не запускается с сообщением об ошибке.

+0

http://stackoverflow.com/questions/8102041/how-to-create-an-override-method-using-mono-cecil this? – usr

+0

Да. Как я сказал: Довольно сильно устарел (2011). По крайней мере, мне не удается просто установить эти атрибуты ... – SharpShade

ответ

0

Решение (благодаря Jb Evain) проста:

Добавить TypeReference к Overrides свойство метода финализатора. Очевидно, что это должно произойти автоматически, когда HideBySig, Виртуальный и ReuseSlot Используется. Просто добавьте ссылку вручную.

destructor.Overrides.Add(someModule.Import(typeof(object).GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance))); 
Смежные вопросы