Как программно определить количество ссылок на метод с C # - PullRequest
5 голосов
/ 20 сентября 2008

Я недавно унаследовал консольное приложение C #, которое нуждается в некотором сокращении и очистке. Короче говоря, приложение состоит из одного класса, содержащего более 110 000 строк кода. Да, более 110 000 строк в одном классе. И, конечно же, приложение является основой нашего бизнеса, круглосуточно обновляя данные, используемые на динамическом веб-сайте. Хотя мне сказали, что мой предшественник был «действительно хорошим программистом», очевидно, что он вообще не был в ООП (или в управлении версиями).

Во всяком случае ... во время ознакомления с кодом я обнаружил множество методов, которые объявлены, но на них никогда не ссылаются. Похоже, что для копирования кода использовалась функция копирования / вставки, например, скажем, у меня есть метод с именем getSomethingImportant (), скорее всего, есть еще один метод с именем getSomethingImortant_July2007 () (в большинстве случаев это шаблон functionName_ [datetamp]). Похоже, что когда программиста попросили внести изменение в getSomethingImportant (), он скопирует / вставит, затем переименует в getSomethingImortant_Date, внесет изменения в getSomethingImortant_Date, затем изменит любые вызовы методов в коде на имя нового метода, оставив старый метод в код, но никогда не ссылаться.

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

Существуют ли классы в .NET Framework, которые я могу использовать для проверки этого кода? Или любые другие полезные инструменты, которые могут помочь идентифицировать методы, которые объявлены, но на которые никогда не ссылаются?

(Дополнительный вопрос: кто-нибудь еще видел такое приложение на C #, один действительно большой класс? Это более или менее один огромный процедурный процесс, я знаю, что это первый раз, который я видел, по крайней мере такого размера.)

Ответы [ 10 ]

12 голосов
/ 20 сентября 2008

Вы можете попробовать использовать NDepend , если вам просто нужно извлечь некоторую статистику о вашем классе. Обратите внимание, что этот инструмент использует Mono.Cecil для внутреннего контроля сборок.

4 голосов
/ 26 октября 2008

Чтобы завершить ответ Romain Verdier , давайте немного углубимся в то, что NDepend может принести вам здесь. ( Отказ от ответственности: я являюсь разработчиком команды NDepend )

NDepend позволяет запрашивать ваш код .NET с помощью некоторых запросов LINQ. Знать, какие методы вызывают и какие другие вызывают, так же просто, как написать следующий запрос 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

4 голосов
/ 20 сентября 2008

Загрузите бесплатную пробную версию от Resharper. Используйте Resharper-> Search-> Find Usages in File (Ctrl-Shift-F7), чтобы выделить все использования. Кроме того, счет появится в строке состояния. Если вы хотите выполнить поиск по нескольким файлам, вы можете сделать это также с помощью Ctrl-Alt-F7.

Если вам это не нравится, выполните текстовый поиск по имени функции в Visual Studio (Ctrl-Shift-F), это должно сообщить вам, сколько случаев было найдено в решении и где они находятся.

1 голос
/ 23 сентября 2008

Если вы не хотите использовать оболочку для NDepend, поскольку кажется, что в одной сборке есть только один класс - закомментируйте методы и скомпилируйте. Если он компилируется, удалите их - у вас не будет проблем с наследованием, виртуальных методов или чего-то в этом роде. Я знаю, это звучит примитивно, но иногда рефакторинг - это просто грубая работа, подобная этой. Это предполагает, что у вас есть модульные тесты, которые вы запускаете после каждой сборки, пока не очистите код (красный / зеленый / рефакторинг).

1 голос
/ 20 сентября 2008

FXCop имеет правило, которое идентифицирует неиспользуемые частные методы. Таким образом, вы можете пометить все методы как закрытые и создать список.

У FXCop также есть язык, если вы хотите стать более любопытным http://www.binarycoder.net/fxcop/

1 голос
/ 20 сентября 2008

Окно Анализатора в Отражатель может показать вам, где вызывается метод (Используется).
Похоже, что получение информации таким образом займет очень много времени.
Вы могли бы взглянуть на API, который Reflector предоставляет для написания надстроек, и посмотреть, сможете ли вы таким образом выполнить основную работу анализа. Я ожидаю, что исходный код для надстройки метрик кода может немного рассказать вам о том, как получить информацию о методах из отражателя API.

Редактировать: Также может помочь надстройка модели кода для Reflector. Это хороший способ изучить API Reflector.

1 голос
/ 20 сентября 2008

Я не думаю, что вы хотите написать это самостоятельно - просто купите NDepend и используйте Язык запросов кода

0 голосов
/ 20 сентября 2008

Попробуйте, чтобы компилятор испускал файлы ассемблера, как в инструкциях 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:», вы знаете, что у вас есть объявление функции / метода, а когда вы видите «call create_secure_tmpfile», вы знаете, что у вас есть ссылка на функцию / метод. Это может быть достаточно для ваших целей, но если нет, это всего лишь несколько шагов, прежде чем вы сможете создать очень симпатичное дерево вызовов для всего приложения.

0 голосов
/ 20 сентября 2008

В самом .NET Framework нет простого инструмента для этого. Однако я не думаю, что вам действительно нужен список неиспользованных методов сразу. Насколько я понимаю, вы просто просмотрите код и для каждого метода проверите, не используется ли он, а затем удалите его, если так. Я бы использовал Visual Studio «Найти ссылки», чтобы сделать это. В качестве альтернативы вы можете использовать Resharper с его окном «Анализ». Или вы можете просто использовать инструмент анализа кода Visual Studio, чтобы найти все неиспользуемые частные методы.

0 голосов
/ 20 сентября 2008

Я не знаю ничего, что было бы разработано для этого конкретного случая, но вы могли бы использовать Mono.Cecil. Отразите сборки, а затем посчитайте ссылки в IL. Не должно быть слишком жестким.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...