I don't think that this information is available for code running
outside the debugger.
If one really needs this info and is willing to add
developer hours and runtime overhead to get a solution,
then there is the swiss-army-knife-for-stuff-not-possible-in-C#
solution: use an AOP weaver to modify the code to do as
required.
Below is an example using my favorite tool AspectDNG. It is
a bit long, but it is not a simple problem.
Arne
====================================
C:\e\callfun>type Trace.cs
using System;
using System.Collections.Generic;
using System.Text;
namespace ESup
{
public class Arg
{
private Type typ;
private object val;
public Arg(Type typ, object val)
{
this.typ = typ;
this.val = val;
}
public Type Typ { get { return typ; } }
public object Val { get { return val; } }
public override string ToString()
{
return typ.Name + ":" + (val != null ? val.ToString() :
"null");
}
}
public class Call
{
private string clznam;
private string metnam;
private IList<Arg> args;
public Call(string clznam, string metnam)
{
this.clznam = clznam;
this.metnam = metnam;
this.args = new List<Arg>();
}
public string Clznam { get { return clznam; } }
public string Metnam { get { return metnam; } }
public IList<Arg> Args { get { return args; } }
public override string ToString()
{
StringBuilder sb = new StringBuilder();
sb.Append(clznam);
sb.Append(".");
sb.Append(metnam);
sb.Append(" -");
foreach(Arg a in args)
{
sb.Append(" ");
sb.Append(a.ToString());
}
return sb.ToString();
}
}
public class Trace
{
private static Trace inst = new Trace();
private Stack<Call> stk;
private Trace()
{
stk = new Stack<Call>();
}
public static Trace Instance { get { return inst; } }
public IEnumerable<Call> Stack { get { return stk; } }
public void Push(Call v)
{
stk.Push(v);
}
public void PushName(string clznam, string metnam)
{
Push(new Call(clznam, metnam));
}
public void PushArg(Type typ, object val)
{
stk.Peek().Args.Add(new Arg(typ, val));
}
public void Pop()
{
stk.Pop();
}
}
}
C:\e\callfun>csc /t:library Trace.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.3053
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
C:\e\callfun>type Test.cs
using System;
using ESup;
namespace E
{
public class Test
{
public void Sub3(int iv, double xv, string sv)
{
Console.WriteLine(iv + " " + xv + " " + (sv ?? "null"));
foreach(Call cal in Trace.Instance.Stack)
{
Console.WriteLine(cal);
}
}
public void Sub2(int iv, double xv)
{
Sub3(iv, xv, "ABC");
Sub3(iv, xv, null);
}
public void Sub1(int iv)
{
Sub2(iv, 123.456);
}
public static void Main(string[] args)
{
Test o = new Test();
o.Sub1(123);
}
}
}
C:\e\callfun>csc /t:exe /r:Trace.dll Test.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.3053
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
C:\e\callfun>Test
123 123,456 ABC
123 123,456 null
C:\e\callfun>type AOPTrace.cs
using System;
using DotNetGuru.AspectDNG.Joinpoints;
namespace ESup
{
public class CallTracker
{
[AroundCall("* E.*::*(*)")]
public static object SaveCall(JoinPoint jp)
{
if(jp is MethodJoinPoint)
{
MethodJoinPoint mjp = (MethodJoinPoint)jp;
Trace.Instance.PushName(mjp.TargetOperation.DeclaringType.FullName,
mjp.TargetOperation.Name);
for (int i = 0; i < mjp.Arguments.Length; i++)
{
Trace.Instance.PushArg(mjp.TargetOperation.GetParameters()
.ParameterType,
mjp.Arguments);
}
}
object res = jp.Proceed();
if(jp is MethodJoinPoint)
{
Trace.Instance.Pop();
}
return res;
}
}
}
C:\e\callfun>csc /t:library /r:AspectDNG.exe /r:Trace.dll AOPTrace.cs
Microsoft (R) Visual C# 2005 Compiler version 8.00.50727.3053
for Microsoft (R) Windows (R) 2005 Framework version 2.0.50727
Copyright (C) Microsoft Corporation 2001-2005. All rights reserved.
C:\e\callfun>AspectDNG Test.exe AOPTrace.dll
C:\e\callfun>Test
123 123,456 ABC
E.Test.Sub3 - Int32:123 Double:123,456 String:ABC
E.Test.Sub2 - Int32:123 Double:123,456
E.Test.Sub1 - Int32:123
123 123,456 null
E.Test.Sub3 - Int32:123 Double:123,456 String:null
E.Test.Sub2 - Int32:123 Double:123,456
E.Test.Sub1 - Int32:123