2016-04-25 15 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 ...抱歉,對此作出延遲迴應。我從來沒有收到通知。非常好的工作。 :) –