C#/ Cecil创建Finalizer重载

时间:2015-08-06 21:57:27

标签: c# cil il mono.cecil

我一整天都在尝试为System.Object.Finalizer() - 方法获取有效的重载。我需要将一个终结器(如果还没有)注入随机类。该方法本身应该工作正常 - 至少反映它看起来有效,我看不到任何CIL问题/错误。

这是创建重载方法的代码:

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#反射时,代码看起来非常好。它甚至说“受保护的覆盖Finalize()”,但PEVerify指出“坏标题”,应用程序甚至没有以错误消息开头。

1 个答案:

答案 0 :(得分:0)

解决方案是(感谢Jb Evain)简单:

TypeReference添加到终结器方法的Overrides属性中。显然,当使用 HideBySig Virtual ReuseSlot 时,这应该会自动发生。否则只需手动添加引用。

destructor.Overrides.Add(someModule.Import(typeof(object).GetMethod("Finalize", BindingFlags.NonPublic | BindingFlags.Instance)));