2008-09-19 70 views
5

我最近繼承了需要某些修剪和清理的C#控制檯應用程序。長話短說,該應用程序由一個包含超過110,000行代碼的類組成。是的,在一個班級中超過110,000行。當然,這款應用程序對我們的業務至關重要,它運行着全天候更新動態網站上使用的數據。儘管我被告知我的前任是「一位非常優秀的程序員」,但顯然他完全沒有進入OOP(或版本控制)。如何以編程方式識別C#方法的引用數量

無論如何...雖然熟悉了代碼,但我發現了很多已聲明但從未引用的方法。它看起來好像是使用複製/粘貼來對代碼進行版本化,例如說我有一個名爲getSomethingImportant()的方法,可能有另一種方法稱爲getSomethingImortant_July2007()(該模式在大多數情況下是functionName_ [datestamp])。它看起來像程序員被要求對getSomethingImportant()進行更改時,他會複製/粘貼,然後重命名爲getSomethingImortant_Date,對getSomethingImortant_Date進行更改,然後將代碼中的任何方法調用更改爲新方法名稱,將舊方法留在代碼但從未引用。

我想編寫一個簡單的控制檯應用程序,通過一個巨大的類爬行,並返回所有方法的列表與每個方法被引用的次數。據我估計,有超過1000種方法,所以手動操作需要一段時間。

.NET Framework中是否有類可用於檢查此代碼?或者可能有助於識別已聲明但從未引用的方法的其他有用工具? (旁邊的問題:有沒有其他人看過這樣的C#應用​​程序,一個reeeealy大類?或多或少是一個巨大的程序過程,我知道這是我見過的第一個,至少是這樣的大小。 )

回答

12

如果您只需要提取一些關於您的班級的統計信息,則可以嘗試使用NDepend。請注意,該工具在內部依靠Mono.Cecil來檢查組件。

0

我不知道任何可以處理這個特定情況的東西,但是您可以使用Mono.Cecil。反映程序集,然後在IL中對引用進行計數。不應該太強悍。

1

我可以用NDepend來做到這一點,但我從來沒有用過它。

1

分析儀窗口Reflector可以告訴你在哪裏調用一個方法(使用)。
聽起來像它需要很長時間才能獲取信息。
您可能會看到Reflector爲編寫加載項提供的API,並查看您是否可以通過這種方式獲得分析工作。我期望code metrics add-in的源代碼可以告訴你一些關於如何從反射器API獲取有關方法的信息。

編輯:此外code model viewer加入反射器也可以幫助。這是探索Reflector API的好方法。

0

在.NET框架本身並沒有簡單的工具可以做到這一點。但是我不認爲你真的需要一次使用未使用的方法列表。正如我所看到的那樣,您只需瀏覽代碼並查看每種方法,然後檢查它是否未使用,然後刪除它,如果是的話。我會使用Visual Studio「查找引用」命令來做到這一點。或者,您可以使用Resharper及其「分析」窗口。或者,您可以使用Visual Studio代碼分析工具來查找所有未使用的私有方法。

+0

你的建議刪除,因爲我去通過代碼是我的第一個念頭了。正如其他人所建議的,我將使用這種方法加上NDepend來做進一步的分析。 – Duffy 2008-09-20 00:05:57

0

你能爲ReSharper得到錢嗎?這是重構的理想工具。

3

下載免費試用 Resharper。使用Resharper-> Search->查找文件中的用法(Ctrl-Shift-F7)突出顯示所有用法。此外,狀態欄中還會顯示計數。如果你想搜索多個文件,你也可以使用Ctrl-Alt-F7進行搜索。

如果您不喜歡這樣做,請在Visual Studio(Ctrl-Shift-F)中對函數名稱進行文本搜索,這應該告訴您在解決方案中找到了多少次事件以及它們在哪裏。

0

要回答你的「側面問題」,從來沒有見過一個壞的,可能是一個好的條目The Daily WTF。可能稱之爲「最終複製/粘貼重用」。

-1

嘗試使編譯器發出彙編文件,如在x86指令中,而不是.NET程序集。

爲什麼?因爲解析彙編代碼比C#代碼或.NET程序集容易得多。

例如,函數/方法的聲明看起來是這樣的:

.string "w+" 
    .text 
    .type create_secure_tmpfile, @function 
create_secure_tmpfile: 
    pushl %ebp 
    movl %esp, %ebp 
    subl $24, %esp 
    movl $-1, -8(%ebp) 
    subl $4, %esp 

和函數/方法的引用會是這個樣子:

subl $12, %esp 
    pushl 24(%ebp) 
    call create_secure_tmpfile 
    addl $16, %esp 
    movl 20(%ebp), %edx 
    movl %eax, (%edx) 

當你看到 「create_secure_tmpfile:」 你知道你有一個函數/方法聲明,當你看到「調用create_secure_tmpfile」時,你知道你有一個函數/方法引用。這可能足以滿足您的需要,但如果不是這樣,那麼只需執行幾個步驟即可爲您的整個應用程序生成一個非常可愛的調用樹。

+0

當.net包含反射庫時,解析彙編程序如何「容易得多」?更不用說像Mono.Cecil這樣的第三方庫。 – 2010-08-06 17:41:52

1

FXCop有一個規則可以識別未使用的私有方法。所以你可以標記所有的方法,並讓它生成一個列表。

FxCop的也有,如果你想獲得一個語言愛好者 http://www.binarycoder.net/fxcop/

1

如果你不想掏出了NDepend的,因爲它聽起來像有隻在單個組件的單一類 - 註釋掉方法和編譯。如果它編譯,刪除它們 - 你不會有任何繼承問題,虛擬方法或類似的東西。我知道這聽起來很原始,但有時候重構只是這樣的咕嚕聲。這是假設你在每次構建之後都進行單元測試,直到你清除了代碼(紅/綠/重構)。

4

要完成Romain Verdier的答案,讓我們來深入瞭解一下NDepend可以帶給你什麼。 (免責聲明:我是NDepend團隊的開發人員

NDepend讓我們用一些LINQ查詢來查詢您的.NET代碼。瞭解哪些方法調用,並通過他人叫,是因爲編寫以下LINQ查詢一樣簡單:

from m in Application.Methods 
select new { m, m.MethodsCalled, m.MethodsCallingMe } 

此查詢的結果呈現的方式,使易於瀏覽調用者和被調用者(及其100 %集成到Visual Studio中)。

NDepend methods callers and callees


還有許多其他的功能NDepend的,可以幫助你。例如,您可以右鍵單擊在Visual Studio中的方法> NDepend的> ...>正在使用我的(直接或間接) ...產生

NDepend Visual Studio method right click

下面的代碼查詢選擇方法。 ..

from m in Methods 
let depth0 = m.DepthOfIsUsing("NUnit.Framework.Constraints.ConstraintExpression.Property(String)") 
where depth0 >= 0 orderby depth0 
select new { m, depth0 } 

...相匹配的直接和間接的呼叫者,以呼叫的深度(1表示直接呼叫者,2表示直接呼叫者呼叫者等)。

NDepend indirect method callers

,然後通過單擊該按鈕出口到圖形,你會得到你的支點方法的調用圖(當然也可能是其他各地的方式,即方法,通過一個特定的直接或間接調用樞軸方法)。

NDepend call graph

相關問題