methodB() と methodC() を呼び出す methodA() があるとします。
methodB() では、methodB1() と methodB2() を呼び出します。
methodC() では、methodC1()、methodC2()、および methodC3() を呼び出します。
最後にメソッドツリーがあります
方法A
方法B
メソッドB1
メソッドB2
メソッドC
メソッドC1
メソッドC2
メソッドC3
このリストを C# コードで取得することは可能ですか?
コール フローの決定について考えるときに最初に頭に浮かぶのは、コール スタックをチェックすることです。しかし、スタック フレームをチェックしても、現在の呼び出し階層しか得られず、以前の呼び出し階層はわかりません。つまり、C3 でスタックフレームをチェックしても、A が B を呼び出した履歴がないため、これは機能しません。
これは、呼び出された各メソッドも何らかの形でこの目標の達成に参加する必要があることを意味します。各メソッドは、呼び出し元がフローを追跡することを望んでいることを何らかの方法で判断する必要があり、必要な情報の提供に貢献する必要があります。しかし、呼び出し可能な各メソッドにコードを追加するのはばかげています。
これを行う別の方法は、各メソッド呼び出しをインターセプトできる人にこれを委任し、呼び出し元がフローを追跡する必要があるかどうかを確認し、後でアクセスできる必要な情報をログに記録することです。これこそまさに、アスペクト指向プログラミング (AOP)の出番だと私が考えるところです。.Net で AOP を使用するには、PostSharp をご覧ください。時間があれば、いくつかのコード サンプルを試してみますが、今のところ、次の URL を参照することしかできません: http://www.postsharp.net
これが役立つことを願っています。
すべての特定の操作を個別のクラスとして実装できる場合 (推奨)、次のようになります。そうでない場合は、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(){}
}