Интерпретация коллекции MethodBody.ExceptionHandlingClauses
Я использую отражение для анализа блоков обработки исключений метода с [ExceptionHandlingClauses]
собственность [MethodBody]
учебный класс. Я не мог понять из Документации MSDN, как ведет себя эта коллекция и как ее интерпретировать. Допустим, вы хотите утверждать, что:
- метод содержит ровно один блок try.
- этот единственный блок содержит ровно один
catch
пункт. - этот единственный блок содержит
finally
пункт.
Пожалуйста, постарайтесь не выводить контекст из следующего кода, поскольку он слишком сложен для объяснения здесь. Это просто иллюстративный код и может быть плохого дизайна. Рассмотрим следующую иерархию:
// Tier 1. Base class.
namespace ProductName
{
// This is not an abstract class.
// These tier 1 class methods to not have implementations or exception handling blocks.
public class Template: System.IDisposable
{
public sealed void Launch () { this.OnLaunch(); }
public sealed void Simulate () { this.OnSimulate(); }
public sealed void Test () { this.OnTest(); }
public sealed void Submit () { this.OnSubmit(); }
public sealed void Exit () { this.OnExit(); }
protected virtual void OnLaunch () { }
protected virtual void OnSimulate () { }
protected virtual bool OnTest () { return (false); }
protected virtual void OnSubmit () { }
protected virtual void OnExit () { }
}
}
// Tier 2. Defines template platforms e.g. Access, Excel, etc.
// These tier 2 classes do not have implementations or exception handling blocks.
namespace ProductName.Access { public class Template: ProductName.Template { } }
namespace ProductName.Excel { public class Template: ProductName.Template { } }
namespace ProductName.Outlook { public class Template: ProductName.Template { } }
namespace ProductName.PowerPoint { public class Template: ProductName.Template { } }
namespace ProductName.Word { public class Template: ProductName.Template { } }
// Tier 3. Defines individual templates in each platform.
// Each platform will have hundreds of classes with a [Template_########] naming convention.
// Each class overrides all virtual methods with exactly one try/catch/finally block in OnTest and none in other methods.
namespace ProductName.Access.Templates { public class Template_00000001: ProductName.Access.Template { } }
namespace ProductName.Excel.Templates { public class Template_00000001: ProductName.Excel.Template { } }
namespace ProductName.Outlook.Templates { public class Template_00000001: ProductName.Outlook.Template { } }
namespace ProductName.PowerPoint.Templates { public class Template_00000001: ProductName.PowerPoint.Template { } }
namespace ProductName.Word.Templates { public class Template_00000001: ProductName.Word.Template { } }
Я уже знаю следующее об этих классах:
- Базовый класс уровня 1 не имеет реализации, поэтому нет блоков обработки исключений.
- Производные классы уровня 2 не имеют реализации, поэтому нет блоков обработки исключений.
- Производные классы уровня 3 имеют реализации всех виртуальных методов, где все методы, кроме
[OnTest]
НЕ содержат блоки обработки исключений. [OnTest]
Метод всех классов Tier 3 содержит ровно один блок обработки исключений, а в некоторых случаях вложенный блок и / или несколько[using]
заявления.
Я получаю все классы уровня 3 из этой сборки, перебираю каждый тип, получаю [MethodInfo]
объекты для каждого метода, получить [MethodBody]
возразить и осмотреть его [ExceptionHandlingClauses]
коллекция. Результат довольно странный для [OnTest]
метод. [ExceptionHandlingClauses]
Коллекция показывает от 0 до 6 предложений, каждое из которых имеет [Flag]
значение любого [Catch]
или же [Finally]
, Кажется, что нет абсолютно никакой корреляции между ожидаемым количеством [catch/finally]
блоки и что показывает эта коллекция.
Иногда это даже показывает два [Finally]
пункты в методах, которые даже не имеют [try/catch]
блок.
Сначала я подумал, что это может быть связано с наследованием, но ни один из базовых классов не имеет реализаций, не говоря уже о блоках обработки исключений.
Некоторое руководство будет оценено.
1 ответ
ExceptionHandlingClauses
свойство предоставляет информацию об условиях обработки исключений в скомпилированном байт-коде. Семантика блоков обработки исключений в байт-коде регулируется стандартом ECMA-335, а не ECMA-334 (стандарт языка C#). Правила для блоков обработки исключений в C# отличаются от правил, налагаемых байт-кодом, поэтому компилятор иногда компилирует код таким образом, что получается то, что кажется странным блоками обработки исключений, но фактически приводит к правильной семантике времени выполнения в соответствии с исходным кодом C#,
В других случаях C# предоставляет "синтаксический сахар" для функций, не поддерживаемых примитивами байт-кода. Например, using
а также lock
операторы в C# оба реализуются путем компиляции до try
/finally
блоки, которые будут включены в ExceptionHandlingClauses
имущество.