我将PostSharp方面(以下实现为AutoData
)应用于测试方法:
[Theory, AutoData( additionalTypes: typeof(MethodFormatter) )]
public void MethodFormatsAsExpected( FormatterFactory sut )
{
var name = MethodBase
.GetCurrentMethod()
.Name; // Resolves to "<MethodFormatsAsExpected>z__OriginalMethod"
}
如您所见,MethodBase.GetCurrentMethod
的结果是返回编织的身体。我想要检索方面编织的(父)目标方法,基本上相当于:
var method = GetType()
.GetMethod( nameof(MethodFormatsAsExpected) )
.Name; // Returns "MethodFormatsAsExpected"
但是以MethodBase.GetCurrentMethod
提供的通用静态方式。
这可能吗?
答案 0 :(得分:1)
就其本身而言,无法在运行时从代码中获取原始方法。
但是,您可以使用方面来增强需要此信息的方法,并记住您在(线程)静态堆栈变量中的方法。
从概念上讲,以下代码使用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的项目中使用时无效。