Само по себе невозможно получить исходный метод из кода во время выполнения.
Однако вы можете использовать аспекты для улучшения методов, в которых вам нужна эта информация, и запомнить, в каком методе вы находитесь в (потоковой) статической переменной стека.
Концептуально следующий код использует AssemblyLevelAspect
, который усиливает все методы, из которых вы называете CurrentMethodService.Get()
с внутренним MethodLevelAspect
, который выталкивает текущий метод в стеке, когда метод выполняется и выскакивает, когда метод выхода.
public static class CurrentMethodServices
{
[ThreadStatic]
private static Stack<MethodBase> slots;
internal static Stack<MethodBase> Slots
{
get { return slots ?? (slots = new Stack<MethodBase>()); }
}
public static MethodBase Get()
{
return Slots.Peek();
}
internal static void Enter(MethodBase slot)
{
Slots.Push(slot);
}
internal static void Exit()
{
Slots.Pop();
}
}
[PSerializable]
[MulticastAttributeUsage(MulticastTargets.Assembly, Inheritance = MulticastInheritance.Multicast)]
public class CurrentMethodPolicy : AssemblyLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
foreach (
MethodUsageCodeReference methodRef in
ReflectionSearch.GetMethodsUsingDeclaration(typeof(CurrentMethodServices).GetMethod("Get",
BindingFlags.Public | BindingFlags.Static)))
{
if ((methodRef.Instructions & MethodUsageInstructions.Call | MethodUsageInstructions.CallVirtual) != 0)
yield return new AspectInstance(methodRef.UsingMethod, new MethodEnhancement());
}
}
[PSerializable]
public class MethodEnhancement : IMethodLevelAspect
{
[PNonSerialized]
private MethodBase method;
public void RuntimeInitialize(MethodBase method)
{
this.method = method;
}
[OnMethodEntryAdvice]
[SelfPointcut]
public void OnMethodEntry(MethodExecutionArgs args)
{
CurrentMethodServices.Enter(this.method);
}
[OnMethodExitAdvice]
[SelfPointcut]
public void OnMethodExit(MethodExecutionArgs args)
{
CurrentMethodServices.Exit();
}
}
}
Чтобы использовать этот аспект, просто примените его к сборке.
[assembly: CurrentMethodPolicy]
Приятным побочным эффектом этого подхода является то, что поиск метода довольно быстр.
Обратите внимание, что вы не должны использовать CurrentMethodServices.Get()
по любым другим аспектам, только в расширенном коде.
Кроме того, установка наследования атрибута на Multicast
заставляет PostSharp применять аспект при ссылках на сборки, поэтому его нужно применять только в сборке, которая объявляет аспект.
Последнее, CurrentMethodServices.Get()
не будет работать, если оно используется в проекте, который не использует PostSharp.
WOW ... извините за задержку в ответе на это. Я так и не получил уведомление. Очень приятная работа. :) –