检测何时“控制流”退出类

时间:2014-08-07 14:12:12

标签: 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();
    }
}

[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");
    }
}

调用Main()后,我得到了一个堆栈跟踪:

Unhandled Exception: System.SystemException: oops
   at Test.Module2.level3()
   at Test.Module2.level2()
   at Test.Module2.level1()
   at Test.Module1.level2()
   at Test.Module1.level1()
   at Test.Module1.Main(String[] args)

问题
当“控制流程”退出类Module2的代码时,如何编写检测时刻的方面?
也就是说,当Test.Module2.level1()完成其工作[这里,由于异常]。

在PostSharp中是否存在任何此快捷方式?

1 个答案:

答案 0 :(得分:0)

最基本的方法是使用OnMethodBoundaryAspect,它允许您处理方法入口和方法退出建议。您将需要计算堆栈上每个特定类的方法数,当此计数从1到0时,控件将离开预期类的方法。

以下是示例方面代码:

[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);
    }
}

您可能需要修改一下这方面的实现,但它可以在基本情况下工作。