Я не уверен, каковы ваши реальные потребности, но вот вариант с низкой арендной платой. Это не совсем «автоматически», но вы можете использовать StackTrace для очистки информации, которую вы ищете, таким образом, чтобы не требовать передачи аргументов - аналогично предложению ckramer относительно перехвата:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace TracingSample
{
class Program
{
static void Main(string[] args)
{
DoSomething();
}
static void DoSomething()
{
LogEnter();
Console.WriteLine("Executing DoSomething");
LogExit();
}
static void LogEnter()
{
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
Console.WriteLine("Entering {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
}
}
static void LogExit()
{
StackTrace trace = new StackTrace();
if (trace.FrameCount > 1)
{
string ns = trace.GetFrame(1).GetMethod().DeclaringType.Namespace;
string typeName = trace.GetFrame(1).GetMethod().DeclaringType.Name;
Console.WriteLine("Exiting {0}.{1}.{2}", ns, typeName, trace.GetFrame(1).GetMethod().Name);
}
}
}
}
Вы можете объединить что-то вроде приведенного выше примера с наследованием, используя не виртуальный открытый член в базовом типе для обозначения метода действия, а затем вызвать виртуального члена для фактического выполнения работы:
public abstract class BaseType
{
public void SomeFunction()
{
LogEnter();
DoSomeFunction();
LogExit();
}
public abstract void DoSomeFunction();
}
public class SubType : BaseType
{
public override void DoSomeFunction()
{
// Implementation of SomeFunction logic here...
}
}
Опять же - в этом нет особого "автоматического" подхода, но он будет работать на ограниченной основе, если вам не потребуется инструментарий при каждом вызове метода.
Надеюсь, это поможет.