2011-01-28 112 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 
        } 
       } 
      } 
     } 
    } 
} 

`