6

假设我们有调用methodB() 和methodC() 的methodA()。

在methodB()中,我们调用methodB1()和methodB2()。

在methodC()中,我们调用methodC1()、methodC2()和methodC3()。

所以最后我们有了方法树

方法A

方法B

方法B1

方法B2

方法C

方法C1

方法C2

方法C3

是否可以通过 C# 代码获得此列表?

4

2 回答 2

2

当我们考虑确定调用流程时,首先想到的是检查调用堆栈。但是检查堆栈帧只能给我们当前的调用层次结构,而不是之前的调用层次结构。即,即使您在 C3 中检查堆栈帧,它也不会有 A 调用 B 的历史记录。所以这不起作用。

这意味着每个被调用的方法也需要以某种方式参与实现这个目标。每个方法都必须以某种方式确定调用者想要跟踪流,并且必须为提供所需信息做出贡献。但是在每个可能调用的方法中添加一些代码是荒谬的。

另一种方法是将其委托给可以拦截每个方法调用的人,检查调用者是否想要跟踪流程并记录以后可以访问的所需信息。这正是我认为面向方面编程(AOP)出现的地方。要在 .Net 中使用 AOP,请查看 PostSharp。如果我有时间,我会尝试提出一些代码示例,但现在我只能指向这个网址:http ://www.postsharp.net

我希望这有帮助。

于 2013-11-11T07:36:24.017 回答
1

如果您能够将每个特定操作实现为单独的类(我建议),则如下所示。如果没有,您应该使用AOP。我会推荐用于 AOP 的Castle Dynamic Proxy 。

class Program
{
    static void Main(string[] args)
    {
        new A().Invoke();
        CallStack.Get().ToList().ForEach(Console.WriteLine);
        Console.ReadKey();
    }
}

public class CallStack
{
    private CallStack()
    {
        _callStack = new Stack<string>();
    }
    private static CallStack _singleton;
    private  Stack<string> _callStack;
    public static CallStack Get()
    {
        if (_singleton == null) _singleton = new CallStack();
        return _singleton;
    }
    public static void Push(string call)
    {
        Get()._callStack.Push(call);
    }
    public List<string> ToList()
    {
        return new List<string>(_callStack);
    }
}

public abstract class MethodBase
{
    protected void Trace()
    {
        CallStack.Push(GetType().Name);
    }
    protected abstract void Operation();
    public void Invoke()
    {
        Trace();
        Operation();
    }
}

public class A : MethodBase
{
    protected override void Operation()
    {
        new B().Invoke();
        new C().Invoke();
    }
}

public class B : MethodBase
{
    protected override void Operation()
    {
        new B1().Invoke();
        new B2().Invoke();
    }
}

public class C : MethodBase
{
    protected override void Operation()
    {
        new C1().Invoke();
        new C2().Invoke();
        new C3().Invoke();
    }
}

public class B1 : MethodBase
{
    protected override void Operation() { }
}

public class B2 : MethodBase
{
    protected override void Operation() { }
}

public class C1 : MethodBase
{
    protected override void Operation() { }
}

public class C2 : MethodBase
{
    protected override void Operation() { }
}

public class C3 : MethodBase
{
    protected override void Operation(){}
}
于 2013-11-11T08:29:22.367 回答