C #: Автоматическое удаление ненужных ссылок на сборки? - PullRequest
3 голосов
/ 28 января 2011

Я работаю с большой кодовой базой с огромным количеством проектов, каждый из которых имеет небольшое (а в некоторых случаях огромное) количество ссылок на другие.Со временем в этой кодовой базе был проведен существенный рефакторинг, и в результате появилось много сборок, на которые ссылаются некоторые проекты только потому, что они содержали класс, который с тех пор был перемещен в другое место;такого рода вещи.

ReSharper имеет интегрированный в IDE инструмент, который позволяет пользователям находить код, который фактически использует заданную ссылку для данного проекта, однако для того, чтобы превратить это в решение, нам необходимо получитьчеловек должен щелкнуть правой кнопкой мыши по каждой ссылке в каждом проекте, а затем проверить, нет ли употреблений, а затем удалить их, что является не только долгим процессом, но и граничит с пытками.

Я бы хотел иметь возможностьавтоматизировать этот процесс, чтобы мы просто запустили его и удалили ненужные ссылки;тогда мы могли бы, возможно, интегрировать его в какой-то регулярный процесс, чтобы не замечать пропущенных ошибок.

Два варианта, о которых я подумал: А) Автоматизировать ReSharper с Powershell, если возможно, или Б), возможно,Диаграммы зависимостей в архитектуре Visual Studio 2010 могут справиться с этим, и, возможно, с помощью сценариев, если мне повезет.

У меня такие вопросы:

  • Может ли ReSharper быть написан для чего-то подобного?
  • Предусматривает ли архитектура VS2010 удаление неиспользуемых ссылок каким-либо пакетным / автоматическим способом?

Ответы [ 3 ]

6 голосов
/ 29 января 2011

Вы должны быть в состоянии сделать это с помощью простого PowerShell:

1) загрузить Visual Studio своим решением

2) скомпилировать все решение

3) оставить VSзапустить и запустить powershell.exe

4) получить ссылку на все еще работающий экземпляр DTE VS из ROT (важно - убедитесь, что запущен только один экземпляр - если он повышен, 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) сравнивают фактические ссылочные сборки со сборками, на которые есть ссылки в проекте, и удаляют избыточные сборки через VS DTEобъектная модель

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

10) прибыль!

Это работает, потому что .net связывает только те сборки, на которые действительно есть ссылки в коде.Извините, я не могу опубликовать полный рабочий пример, но этого должно быть достаточно, чтобы вы начали.

-Oisin

1 голос
/ 05 декабря 2012

Я следовал инструкциям @ x0n, но у меня это не получилось.Может быть, я что-то упустил.Я должен признать, что не смог загрузить свои dll s ReflectionOnlyLoad из-за ошибки COM.Поэтому я загрузил их LoadFile.Ссылки на сборки, предоставленные LoadFile, были точно такими же, когда я загружал сборку с помощью Reflector.В конце мой скрипт PowerShell сгенерировал список, показывающий ссылки, которые есть в проекте, но не загружены сборкой.Теоретически это должны быть «ненужные» ссылки.Когда я начал их удалять, сборка не удалась.Например, в случае моего первого проекта отсутствие какой-либо из 4 «ненужных» ссылок приведет к сбою сборки.Я просматриваю вывод сценария powershell, и в нем тоже есть список "System", например.Если я его уберу, компилятор даже не будет жаловаться на кучу «using System;», но до этого не получится - заявив, что мне нужно ссылаться на эту сборку из-за интерфейса ... Кстати, наш проект не игрушка,он включает в себя 140+ dll (хотя почти половина из них - Test nUnit dll), и я подумал, что я сделаю кое-что.Мой скрипт (который не рекурсивно переходит в папки проекта - некоторые проекты содержат больше 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
                    }
                }
            }
        }
    }
}

`

1 голос
/ 29 января 2011

Не полное решение, но посмотрите на Разрешение зависимостей csproj, когда проекты также зависят от сборок из bin * и Как найти неправильные зависимости сборки через PowerShell .Есть способ найти ссылки на другие проекты и найти ссылки в сборке.

Вторая часть такая же, как предложила Ойсин.Первый немного отличается - он берет ссылки из файла csproj (взятый как файл xml и обработанный таким образом).

Принимайте это хотя бы как вдохновение;)

...