2016-04-25 65 views
0

我有一个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提供了一个通用的,静态的方式。

这可能吗?

回答

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的项目中使用时不起作用。

+0

WOW ...抱歉,对此作出延迟回应。我从来没有收到通知。非常好的工作。 :) –