2010-01-25 28 views
3

一個電話我正在尋找一種方法,以確保方法「A」調用方法「B」。因此粗略地說,這筆交易是..C#反思 - 我可以檢查,如果一個方法向另一

class one 
{ 
    internal static void MethodA() 
    { 
     //Do Something here. SHOULD be calling B. 
    } 

    void MethodB() 
    { 
     //MUST be called by MethodA. 
    } 
} 

class two 
{ 
    internal void MethodA() 
    { 
     //Test that MethodA calls MethodB 
    } 
} 

我要指出,我是卡在NET 2.0這一個如此ExpressionTrees是一個沒有去。我甚至不確定他們會幫忙,但那是我最初的想法。

編輯:這是一個內部工具,以可視化圈來源的複雜性,所以我不關心這裏打破封裝。另外,這很可能只需要使用System.Reflection就可以完成。

回答

2

雖然有一個IL閱讀器的codeproject片段,但您可能必須爲它支持泛型支持。

http://www.codeproject.com/KB/cs/sdilreader.aspx

玩得開心!

+0

我在看完MethodBody類之後,就遇到了同樣的文章。雖然好電話。有一個大綠色的勾號。 – Stimul8d 2010-01-25 15:50:02

1

也許不是你要找什麼,但你可以寫用諷刺的框架單元測試。這個嘲諷的框架(比如Moq)可以驗證一個方法是否在模擬中被調用,當執行一些代碼時。

+0

我如何使用Moq。我個人使用它,但不能在工作。 這個人必須用恐懼的框架完成。 – Stimul8d 2010-01-25 14:30:25

2

您可以使用Mono Cecil來反映MethodA的方法體並查找call/callvirt指令,其中調用MethodB

+0

嗯,我不能使用單聲道,但你把我放到MethodBody類。從來沒有遇到過這種情況。可能有用。 – Stimul8d 2010-01-25 14:41:06

+2

如果您不能使用任何外部組件,那麼你可以做'MethodBody'的一些最起碼的分析,找到'呼叫/ callvirt'指令和這些指令的元數據標記,然後使用'Module.ResolveMethod'。 – 2010-01-25 15:09:38

+0

順便說一句,你不需要使用單聲道,如果你只想使用單聲道塞西爾,它也可以在.net 2.0上運行。 – 2010-01-25 15:13:38

1

說實話,我覺得你太八卦有關執行類的內部細節。

至於答案,我提供一個對應,可以考慮:

void MethodB() { 
    var methodA = BuildDelegate("Method" + "A"); 
    methodA(); 
} 
+0

一致認爲,...這樣的方式,但這是有點在這種情況下的應用程序,..這不是生產代碼或單元測試,..它是一個內部工具。 – Stimul8d 2010-01-25 14:46:13

1

你不能手卷模仿對象?這取決於您是否可以使MethodB可見和虛擬。

class one 
{ 
    internal static void MethodA() 
    { 
     //Do Something here. SHOULD be calling B. 
    } 

    internal virtual void MethodB() 
    { 
     //MUST be called by MethodA. 
    } 
} 

class three : one 
{ 
    public bool wasCalled; 
    override void MethodB() 
    { 
     wasCalled=true; 
    } 
} 


class two 
{ 
    internal void MethodA() 
    { 
     three.ClassA(); 
     if (three.wasCalled) 
     { 
     } 
    } 
} 
+0

我可以做到這一點。但在這種情況下,我需要認真努力,因爲這些模擬需要動態創建。我需要重新考慮我想的這個問題。我正在研究在這個工具中可視化圈複雜性,並且我沒有在問題中得到這個結論。 – Stimul8d 2010-01-25 15:01:35

3

這是在許多情況下是可行的,但要採取一些打字你的一部分。你想要做的第一件事是使用一個ILReader類 - 有一個概要one here(和the one that Florian Doyon posted)。然後,你想換行,在這樣的一類:

public class MethodCalls : IEnumerable<MethodInfo> 
{ 
    MethodBase _method; 

    public MethodCalls(MethodBase method) 
    { 
     _method = method; 
    } 

    public IEnumerator<MethodInfo> GetEnumerator() 
    { 
     // see here: http://blogs.msdn.com/haibo_luo/archive/2005/10/04/476242.aspx 
     ILReader reader = new ILReader(_method); 

     foreach (ILInstruction instruction in reader) { 
      CallInstruction call = instruction as CallInstruction; 
      CallVirtInstruction callvirt = instruction as CallVirstInstruction; 
      if (call != null) 
      { 
       yield return ToMethodInfo(call); 
      } 
      else if (callvirt != null) 
      { 
       yield return ToMethodInfo(callvirt); 
      } 
     } 
    } 
} 

MethodInfo ToMethodInfo(CallInstruction instr) { /* ... */ } 

MethodInfo ToMethodInfo(CallVirtInstruction instr) { /* ... */ } 

無論ToMethodInfo的兩種口味的定義,因爲CallInstruction也不會被定義。儘管如此,這個大綱有望將您的問題變爲:

public static bool Calls(MethodBase caller, MethodInfo callee) 
{ 
    return new MethodCalls(caller).Contains(callee); 
} 
+0

我的我,你是不是一個聰明的獾!非常有幫助,謝謝。 – Stimul8d 2010-01-26 10:31:38

相關問題