6

Let's say we have methodA() that calls methodB() and methodC().

In methodB(), we call methodB1() and methodB2().

In methodC(), we call methodC1(), methodC2() and methodC3().

So at the end we have the method tree

methodA

methodB

methodB1

methodB2

methodC

methodC1

methodC2

methodC3

Is it possible to have this list via C# code?

Cettt
  • 11,460
  • 7
  • 35
  • 58
Nam G VU
  • 33,193
  • 69
  • 233
  • 372
  • 3
    possible duplicate of [Answering "Which method called me?" at the run-time in .NET? Or is CallStack data readable by the code?](http://stackoverflow.com/questions/1873998/answering-which-method-called-me-at-the-run-time-in-net-or-is-callstack-dat) – Ken White Nov 11 '13 at 06:47
  • 1
    you could get the IL of a method and analyze the opcodes searching for method calls... – DarkSquirrel42 Nov 11 '13 at 06:50
  • 1
    Would you like to have that list in runtime or compile-time? – Ondrej Janacek Nov 11 '13 at 06:51
  • 3
    @KenWhite: I don't think OP wants a stack trace. It seems like he wants to get a hierarchical view of all calls originating from a single method. – vgru Nov 11 '13 at 08:01
  • @OndrejJanacek I love to have it in runtime – Nam G VU Nov 11 '13 at 09:59

2 Answers2

2

The first thing that comes to our mind when we think about determining the call flow is to check the call stack. But checking stack frames can only give us the current call hierarchy and not the previous one. i.e Even if you check stackframes in C3, it wont have the history of A calling B. So this wont work.

This means that each called method also somehow needs to participate in achieving this goal. Each method has to somehow determine that the caller is wanting to track the flow and has to contribute towards providing the required information. But adding some code in each possible method that can be called is just ridiculous.

Another way of doing this is to delegate this to someone who can intercept each method invocation, check if caller is wanting to track the flow and log the required information which can be accessed later. This is exactly where i think Aspect Oriented Programming (AOP) comes into the picture. To use AOP in .Net please have a look at PostSharp. If i get time i will try and come up with some code sample but for now i can only point you to this url: http://www.postsharp.net

I hope this helps.

Vinod Kumar Y S
  • 628
  • 3
  • 9
1

If you are able to implement every particular operation as a seperate class (what I recommend), it would be as follows. If not, you should use AOP. I would recommend Castle Dynamic Proxy for 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(){}
}
mehmet mecek
  • 2,615
  • 2
  • 21
  • 25