我正在使用Mono.Cecil在屬性setter中注入一些指令,注入Brfalse_s
指令時我有奇怪的錯誤。這裏是代碼,簡短。Mono.Cecil指令標籤解析
private void InjectNullProtection(PropertyDefinition property)
{
IList<Instruction> instructions = property.SetMethod.Body.Instructions;
Instruction first = instructions.First();
if (!property.SetMethod.Body.Variables.Any(v => v.VariableType.FullName == GetTypeReference(typeof(bool)).FullName))
{
property.SetMethod.Body.Variables.Add(new VariableDefinition(GetTypeReference(typeof(bool))));
}
ILProcessor processor = property.SetMethod.Body.GetILProcessor();
Instruction ret = instructions.Single(i => i.OpCode.Code == Code.Ret);
processor.InsertBefore(first, processor.Create(OpCodes.Nop));
processor.InsertBefore(first, processor.Create(OpCodes.Ldarg_1));
processor.InsertBefore(first, processor.Create(OpCodes.Ldnull));
processor.InsertBefore(first, processor.Create(OpCodes.Cgt_Un));
processor.InsertBefore(first, processor.Create(OpCodes.Stloc_0));
processor.InsertBefore(first, processor.Create(OpCodes.Ldloc_0));
processor.InsertBefore(first, processor.Create(OpCodes.Brfalse_S, ret));
}
如果目標設置器沒有任何try/catch
塊,則一切正常。但是如果在setter中有try/catch
塊,則對於Brfalse_s
指令的目標標籤是錯誤的,而不是Ret
指令標籤,它具有來自try
塊之一的指令標籤。下面是示例:
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldnull
IL_0003: cgt.un
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0037
IL_0009: nop
IL_000a: ldarg.0
IL_000b: ldstr "Name"
IL_0010: callvirt instance void WpfApplication2.Observable1::OnPropertyChanging(string)
IL_0015: nop
IL_0016: ldarg.0
IL_0017: ldarg.1
IL_0018: stfld string WpfApplication2.Observable1::'<Name>k__BackingField'
IL_001d: ldarg.0
IL_001e: ldstr "Name"
IL_0023: callvirt instance void WpfApplication2.Observable1::OnPropertyChanged(string)
IL_0028: nop
IL_0029: nop
IL_002a: ldarg.0
IL_002b: ldstr "FullName"
IL_0030: callvirt instance void WpfApplication2.Observable1::OnPropertyChanged(string)
IL_0035: nop
IL_0036: nop
IL_0037: ret
在這裏你可以看到Brfalse_s
具有IL_0037
目標標籤,這是正確的。但在下一個例子中,出現了一些問題。
IL_0000: nop
IL_0001: ldarg.1
IL_0002: ldnull
IL_0003: cgt.un
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: brfalse.s IL_0011
IL_0009: nop
.try
{
IL_000a: nop
IL_000b: ldarg.0
IL_000c: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0011: ldarg.0
IL_0012: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0018: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_001d: callvirt instance void WpfApplication2.Observable2::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_0022: nop
IL_0023: ldarg.0
IL_0024: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0029: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_002e: ldarg.0
IL_002f: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0035: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_003a: callvirt instance void WpfApplication2.Observable3::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_003f: nop
IL_0040: ldarg.0
IL_0041: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0046: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_004b: callvirt instance class WpfApplication2.Observable4 WpfApplication2.Observable3::get_Observable4()
IL_0050: ldarg.0
IL_0051: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3Observable4PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0057: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_005c: callvirt instance void WpfApplication2.Observable4::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_0061: nop
IL_0062: ldarg.0
IL_0063: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0068: ldarg.0
IL_0069: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_006f: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_0074: callvirt instance void WpfApplication2.Observable2::remove_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_0079: nop
IL_007a: ldarg.0
IL_007b: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0080: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_0085: ldarg.0
IL_0086: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_008c: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_0091: callvirt instance void WpfApplication2.Observable3::remove_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_0096: nop
IL_0097: leave.s IL_009e
} // end .try
catch [mscorlib]System.NullReferenceException
{
IL_0099: pop
IL_009a: nop
IL_009b: nop
IL_009c: leave.s IL_009e
} // end handler
IL_009e: nop
IL_009f: nop
.try
{
IL_00a0: nop
IL_00a1: ldarg.0
IL_00a2: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_00a7: ldarg.0
IL_00a8: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_00ae: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_00b3: callvirt instance void WpfApplication2.Observable2::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_00b8: nop
IL_00b9: ldarg.0
IL_00ba: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_00bf: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_00c4: ldarg.0
IL_00c5: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2Observable3PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_00cb: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_00d0: callvirt instance void WpfApplication2.Observable3::remove_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_00d5: nop
IL_00d6: ldarg.0
IL_00d7: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_00dc: ldarg.0
IL_00dd: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_00e3: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_00e8: callvirt instance void WpfApplication2.Observable2::remove_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_00ed: nop
IL_00ee: leave.s IL_00f5
} // end .try
catch [mscorlib]System.NullReferenceException
{
IL_00f0: pop
IL_00f1: nop
IL_00f2: nop
IL_00f3: leave.s IL_00f5
} // end handler
IL_00f5: nop
IL_00f6: nop
IL_00f7: ldarg.0
IL_00f8: ldstr "Observable2"
IL_00fd: callvirt instance void WpfApplication2.Observable1::OnPropertyChanging(string)
IL_0102: nop
IL_0103: ldarg.0
IL_0104: ldarg.1
IL_0105: stfld class WpfApplication2.Observable2 WpfApplication2.Observable1::'<Observable2>k__BackingField'
IL_010a: nop
.try
{
IL_010b: nop
IL_010c: ldarg.0
IL_010d: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0112: ldarg.0
IL_0113: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0119: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_011e: callvirt instance void WpfApplication2.Observable2::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_0123: nop
IL_0124: ldarg.0
IL_0125: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_012a: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_012f: ldarg.0
IL_0130: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0136: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_013b: callvirt instance void WpfApplication2.Observable3::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_0140: nop
IL_0141: ldarg.0
IL_0142: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0147: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_014c: callvirt instance class WpfApplication2.Observable4 WpfApplication2.Observable3::get_Observable4()
IL_0151: ldarg.0
IL_0152: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3Observable4PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0158: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_015d: callvirt instance void WpfApplication2.Observable4::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_0162: nop
IL_0163: ldarg.0
IL_0164: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0169: ldarg.0
IL_016a: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_0170: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_0175: callvirt instance void WpfApplication2.Observable2::add_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_017a: nop
IL_017b: ldarg.0
IL_017c: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_0181: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_0186: ldarg.0
IL_0187: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Observable4Name_OnObservable2Observable3PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_018d: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_0192: callvirt instance void WpfApplication2.Observable3::add_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_0197: nop
IL_0198: leave.s IL_019f
} // end .try
catch [mscorlib]System.NullReferenceException
{
IL_019a: pop
IL_019b: nop
IL_019c: nop
IL_019d: leave.s IL_019f
} // end handler
IL_019f: nop
IL_01a0: nop
.try
{
IL_01a1: nop
IL_01a2: ldarg.0
IL_01a3: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_01a8: ldarg.0
IL_01a9: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_01af: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_01b4: callvirt instance void WpfApplication2.Observable2::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_01b9: nop
IL_01ba: ldarg.0
IL_01bb: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_01c0: callvirt instance class WpfApplication2.Observable3 WpfApplication2.Observable2::get_Observable3()
IL_01c5: ldarg.0
IL_01c6: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2Observable3PropertyChanged(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_01cc: newobj instance void [System]System.ComponentModel.PropertyChangedEventHandler::.ctor(object, native int)
IL_01d1: callvirt instance void WpfApplication2.Observable3::add_PropertyChanged(class [System]System.ComponentModel.PropertyChangedEventHandler)
IL_01d6: nop
IL_01d7: ldarg.0
IL_01d8: call instance class WpfApplication2.Observable2 WpfApplication2.Observable1::get_Observable2()
IL_01dd: ldarg.0
IL_01de: ldftn instance void WpfApplication2.Observable1::FullName_Observable2Observable3Name_OnObservable2PropertyChanging(object, class [System]System.ComponentModel.PropertyChangedEventArgs)
IL_01e4: newobj instance void [System]System.ComponentModel.PropertyChangingEventHandler::.ctor(object, native int)
IL_01e9: callvirt instance void WpfApplication2.Observable2::add_PropertyChanging(class [System]System.ComponentModel.PropertyChangingEventHandler)
IL_01ee: nop
IL_01ef: leave.s IL_01f6
} // end .try
catch [mscorlib]System.NullReferenceException
{
IL_01f1: pop
IL_01f2: nop
IL_01f3: nop
IL_01f4: leave.s IL_01f6
} // end handler
IL_01f6: nop
IL_01f7: ldarg.0
IL_01f8: ldstr "Observable2"
IL_01fd: callvirt instance void WpfApplication2.Observable1::OnPropertyChanged(string)
IL_0202: nop
IL_0203: nop
IL_0204: ldarg.0
IL_0205: ldstr "FullName"
IL_020a: callvirt instance void WpfApplication2.Observable1::OnPropertyChanged(string)
IL_020f: nop
IL_0210: nop
IL_0211: ret
這裏,Brfalse_s
有IL_0011
爲目標標籤,而不是IL_0211
。
爲什麼'stloc' +'ldloc'?如果你直接使用了結果,你可以通過添加一個變量來節省工作量。你有什麼理由不使用一個'brnull'而不是那些比較?你只是發出最初由C#編譯器生成的代碼(顯然是在調試中)? – Luaan
我不是IL專家:)我剛開始學習它,並且我編寫C#代碼,並且使用ILSpy來查看IL輸出,並將它們複製到D:我如何直接使用結果? –
如果我正確理解你的代碼,你想要做的事情基本上是'if(arg1!= null)return;',對吧?這可以通過簡單的'ldarg.1'完成,後面跟'brnull theretlabel'。即使你決定保留你的原始代碼,IL也是基於堆棧的,所以當'cgt.un'返回一個值時,它將它返回到(虛擬)堆棧 - 它可以立即被'brfalse'使用而不用存儲它在一個變量中。最初的'nop'也是不必要的 - 編譯器使用它來允許調試器注入代碼,但你並不需要。 – Luaan