C# 检测“控制流”何时退出类
假设我有一个代码:C# 检测“控制流”何时退出类,c#,aop,postsharp,C#,Aop,Postsharp,假设我有一个代码: class Module1 { public static void Main(string[] args) { Module1.level1(); } public static void level1() { Module1.level2(); } public static void level2() { Module2.level1(); } } [DetectWhenF
class Module1 {
public static void Main(string[] args) {
Module1.level1();
}
public static void level1() {
Module1.level2();
}
public static void level2() {
Module2.level1();
}
}
[DetectWhenFlowExitsClass] // <-- note aspect
class Module2 {
public static void level1() {
Module2.level2();
}
public static void level2() {
Module2.level3();
}
public static void level3() {
throw new SystemException("oops");
}
}
问题:
如何编写检测控制流退出Module2类代码时刻的方面?
也就是说,当Test.Module2.level1完成其工作时[此处,由于异常]
在PostSharp中是否存在此方面的快捷方式?最基本的方法是使用OnMethodBoundaryAspect,它允许您处理方法输入和方法输出建议。您需要计算堆栈上每个特定类的方法数,当该计数从1变为0时,控件将保留aspected类的方法 以下是示例方面代码:
[Serializable]
public class DetectWhenFlowExitsClass : OnMethodBoundaryAspect
{
[ThreadStatic] private static Dictionary<Type, int> stackCounters;
private Type declaringType;
public override bool CompileTimeValidate(MethodBase method)
{
declaringType = method.DeclaringType;
return true;
}
private void EnsureStackCounters()
{
if (stackCounters == null)
stackCounters = new Dictionary<Type, int>();
}
public override void OnEntry(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = ++counter;
}
public override void OnExit(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = --counter;
if (counter == 0)
Console.WriteLine("Control leaving class {0}", declaringType.Name);
}
}
您可能需要稍微修改一下这个方面的实现,但它可以在基本情况下工作。当堆栈包含level2、level2、level1、level2时该怎么办?代码路径在逻辑上不“属于一个类”。检查为什么要这样做,它似乎关闭了。我需要它,因为在异常之后,我想记录最终的对象状态。但我现在认为这是一种错误的做法。从引发异常的第一个方法退出时应记录对象状态[此处为Module2.level3]。日志记录进一步退出[即来自方法:Module.level2 level1]应该被忽略。@Steve注意,这个问题用AOP和PostSharp标记。PostSharp在程序集中搜索称为方面的特殊属性,这些属性告诉程序集如何更改程序集。因此,你的评论与此无关。@DanielBals:好主意。虽然我不得不改变方法。反正是Tnx。
[Serializable]
public class DetectWhenFlowExitsClass : OnMethodBoundaryAspect
{
[ThreadStatic] private static Dictionary<Type, int> stackCounters;
private Type declaringType;
public override bool CompileTimeValidate(MethodBase method)
{
declaringType = method.DeclaringType;
return true;
}
private void EnsureStackCounters()
{
if (stackCounters == null)
stackCounters = new Dictionary<Type, int>();
}
public override void OnEntry(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = ++counter;
}
public override void OnExit(MethodExecutionArgs args)
{
EnsureStackCounters();
int counter;
stackCounters.TryGetValue(declaringType, out counter);
stackCounters[declaringType] = --counter;
if (counter == 0)
Console.WriteLine("Control leaving class {0}", declaringType.Name);
}
}