2011-01-28 110 views
3

我正在處理一個龐大的代碼庫,其中有大量的項目,其中每個項目都有少量(在某些情況下,大量)引用其他項目。隨着時間的推移,在這個代碼庫上進行了大量的重構,結果有很多程序集被某些項目引用,僅僅是因爲它們曾經包含一個已經移動到別處的類;之類的東西。C#:自動刪除不必要的程序集引用?

ReSharper有一個集成到IDE中的工具,允許用戶找到實際使用給定項目的給定參考的代碼,但是爲了將其轉化爲解決方案,我們需要讓一個人右鍵點擊每個在每個項目中引用,然後實際檢查沒有使用,然後刪除它們,這不僅是一個漫長的過程,而且它也接近酷刑。

我希望能夠自動執行此過程,以便我們只運行它並刪除不必要的引用;那麼我們或許可以將它整合到某種規則的過程中,以便可以發現被忽視的錯誤。

我想到的兩個選項是A)使用Powershell自動化ReSharper,如果可能的話,或者B)Visual Studio 2010體系結構依賴關係圖可以處理這個問題,如果我運氣好的話也許可以用腳本方式。

我的問題是:

  • 燦ReSharper的照本宣科這樣的事情?
  • VS2010體系結構是否提供以任何批次/自動方式刪除未使用的引用?

回答

6

你應該能夠只是簡單的PowerShell來做到這一點:

1)負載解決方案

2)的Visual Studio編譯整個解決方案

3)離開VS運行和啓動powershell.exe

4)從ROT中獲取對VS的DTE仍然運行的實例的引用(重要的 - 確保只有一個實例正在運行 - 如果它的提升,powershell也應該如此):

ps> $dte = [System.Runtime.InteropServices.Marshal]::GetActiveObject("visualstudio.dte") 

5)測試通過枚舉所有項目在其引用的解決方案:

ps> $dte.solution.projects | select @{l="name";e={$_.name}}, ` 
     @{l="references";e={$_.object.references|select -exp name}} | ft -auto 

...轉儲所有的項目名稱和參考...

6)現在,寫一些腳本來遍歷解決方案文件夾和項目

7)當你打的bin \文件夾中,加載了裝配與反思僅負載:

$assembly = [reflection.assembly]::reflectiononlyload($dll) 

8)得到實際引用的程序在你的輸出裝配

$refs = $assembly.getreferencedassemblies() 

9)比較ACTU人引用的程序集到項目中引用的組件,並通過VS DTE對象模型

# example 
$currentproj.object.references.item("system.core").remove() 
$currentproj.save() 

10)利潤去掉多餘的!

這是可行的,因爲.net只鏈接代碼中實際引用的程序集。對不起,我無法發佈一個完整的工作示例,但這應該足以讓您開始。

-Oisin

+0

它的晚了,但我會盡力在本週末博客我的博客上一個完整的工作示例(www.nivot.org) – x0n 2011-01-29 05:44:17

1

我跟着@ x0n的指示,但它並沒有爲我工作搞好。也許我錯過了一些東西。我不得不承認,由於COM錯誤,我無法加載我的dll s與ReflectionOnlyLoad。所以我加載他們LoadFile。當我使用Reflector加載程序集時,由LoadFile提供的程序集引用完全相同。最後,我的PowerShell腳本生成一個列表,顯示項目中但未由程序集加載的引用。理論上這些應該是「不必要」的參考。當我開始刪除它們時,構建失敗。例如,在我的第一個項目中,缺少任何4個「不必要」的引用都會導致構建失敗。例如,我瀏覽了PowerShell腳本的輸出,並列出了「System」。如果我刪除它,編譯器甚至不會抱怨一堆「using System;」,但它在此之前失敗 - 說明我需要引用該程序集,因爲接口... 順便說一句,我們的項目不是玩具,它涉及140+ dll(其中幾乎一半是測試nUnit DLL雖然),我想我會做一些houskeeping。 我的腳本(不遞歸進入項目文件夾 - 有些項目包含多個DLL),所以也許有人可以使用它:

'
$ DTE = [System.Runtime.InteropServices.Marshal] :: GetActiveObject( 「visualstudio.dte」)

$binfiles=Get-ChildItem C:\YourSourcePath\bin\debug 
$dlls=$binfiles | where { $_.extension -eq ".dll" -and $_.name -like "*YourCompanyName*" } 

foreach ($dll in $dlls) { 
    foreach($prj in $dte.solution.projects) { 
     if ($prj.Kind -eq "{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") { 
      if ($prj.Properties.Item("OutputFileName").Value -eq $dll.Name) { 
       $loaded = [reflection.assembly]::LoadFile($dll.FullName) 
       $refs = $loaded.GetReferencedAssemblies() 
       Write "=============" 
       Write $dll.Name 
       Write "-------------" 
       foreach($pref in $prj.Object.References) { 
        $found = 0 
        foreach($ref in $refs) { 
         if ($ref.Name -eq $pref.Name) { 
          $found = 1 
          break; 
         } 
        } 
        if ($found -eq 0) { 
         Write $pref.Name 
        } 
       } 
      } 
     } 
    } 
} 

`