假设我们有methodA()调用methodB()和methodC()。
在methodB()中,我们调用methodB1()和methodB2()。
在methodC()中,我们调用methodC1(),methodC2()和methodC3()。
所以最后我们有了方法树
了methodA
的methodB
methodB1
methodB2
methodC
methodC1
methodC2
methodC3
是否可以通过C#代码获取此列表?
答案 0 :(得分:2)
当我们考虑确定呼叫流程时,首先想到的是检查调用堆栈。但是检查堆栈帧只能给我们当前的调用层次结构,而不是前一个。即使你检查C3中的堆栈帧,它也没有A调用B的历史。所以这不会工作。
这意味着每个被调用的方法也需要以某种方式参与实现这一目标。每种方法都必须以某种方式确定呼叫者想要跟踪流量并且必须有助于提供所需信息。但是,在每种可能被调用的方法中添加一些代码都是荒谬的。
另一种方法是将此委托给可以拦截每个方法调用的人,检查调用者是否要跟踪流并记录以后可以访问的所需信息。这正是我认为面向方面编程(AOP)出现在图片中的地方。要在.Net中使用AOP,请查看PostSharp。如果我有时间,我会尝试提出一些代码示例,但现在我只能指出这个网址:http://www.postsharp.net
我希望这会有所帮助。
答案 1 :(得分:1)
如果您能够将每个特定操作作为单独的类(我推荐的)实现,那么它将如下所示。如果没有,您应该使用AOP。我建议将Castle Dynamic Proxy用于AOP。
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(){}
}