Подтвердить что ты не робот

С# отражение и поиск всех ссылок

Учитывая DLL файл, я хотел бы найти все вызовы метода в этом DLL файле. Как я могу это сделать?

По существу, как я могу программным образом сделать то, что Visual Studio уже делает?

Я не хочу использовать этот инструмент, например .NET Reflector, но отражение прекрасное и, возможно, необходимо.

4b9b3361

Ответ 1

Чтобы узнать, где используется метод MyClass.Foo(), вам необходимо проанализировать все классы всех сборок, которые имеют ссылку на сборку, содержащую MyClass. Я написал простое доказательство того, как выглядит этот код. В моем примере я использовал эту библиотеку (это просто один файл .cs), написанной Jb Evain:

Я написал небольшой тестовый класс для анализа:

public class TestClass
{
    public void Test()
    {
        Console.WriteLine("Test");
        Console.Write(10);
        DateTime date = DateTime.Now;
        Console.WriteLine(date);
    }
}

И я написал этот код, чтобы распечатать все методы, используемые в TestClass.Test():

MethodBase methodBase = typeof(TestClass).GetMethod("Test");
var instructions = MethodBodyReader.GetInstructions(methodBase);

foreach (Instruction instruction in instructions)
{
    MethodInfo methodInfo = instruction.Operand as MethodInfo;

    if(methodInfo != null)
    {
        Type type = methodInfo.DeclaringType;
        ParameterInfo[] parameters = methodInfo.GetParameters();

        Console.WriteLine("{0}.{1}({2});",
            type.FullName,
            methodInfo.Name,
            String.Join(", ", parameters.Select(p => p.ParameterType.FullName + " " + p.Name).ToArray())
        );
    }
}

Он дал мне следующий результат:

System.Console.WriteLine(System.String value);
System.Console.Write(System.Int32 value);
System.DateTime.get_Now();
System.Console.WriteLine(System.Object value);

Этот пример, очевидно, далек от завершения, поскольку он не обрабатывает параметры ref и out и не обрабатывает общие аргументы. Я уверен, что забыл и о других деталях. Он просто показывает, что это можно сделать.

Ответ 2

Одного отражения недостаточно, чтобы найти все ссылки на метод в данной сборке. Reflection дает вам массив байтов для тела любого конкретного метода (MethodInfo.GetMethodBody.GetILAsByteArray), и вы должны сами проанализировать его для ссылок на другие методы. Есть несколько общедоступных библиотек CIL читателей (я их не использовал - надеюсь, кто-то опубликует на нем больше).

Добавление FxCop - в зависимости от вашего сценария вы можете повторно использовать логику синтаксического анализа CIL, предоставленную FxCop (анализ кода Visual Studio ) и добавьте свои пользовательские правила, если запустить его как часть анализа кода, подходит для вас.

Ответ 4

Я бы подумал о том, чтобы отразить сборки Visual Studio и посмотреть, можете ли вы найти их в обратной базе кода. Я считаю, что VS фактически переводит код, а не отражает. Отражение, как написал Майкл, отлично подходит для определения бит сборки, но не для потребителей этих бит. Однако я не пересматривал размышления, чтобы подтвердить свои подозрения.

Ответ 5

См. вопрос о переполнении стека Получить список функций для DLL.

Снято с вышеизложенного (спасибо Jon Skeet):

Для конкретной сборки вы можете использовать Assembly.GetTypes для получения типов, затем для каждого типа вызова Type.GetMethods(), Type.GetProperties() и т.д. или просто Type.GetMembers().

Однако для функциональности плагинов обычно неплохо иметь общий интерфейс, который должны реализовывать плагины, что уменьшает количество отражений, которое вам нужно использовать. Используйте Type.IsAssignableFrom(), чтобы проверить, совместим ли тип с конкретным интерфейсом.

Возможно, вам также стоит взглянуть на Framework Managed Extensibility Framework, который упростит внедрение системы расширения.