Полное руководство по языку программирования С# 14 и платформе .NET 10 / Рефлексия

Исследование методов и конструкторов с помощью рефлексии

Начальный ⏱ 8 мин чтения 👁 2 🕓 обновлено 11.08.2026

Получение информации о методах

Для получения получении информации отдельно о методах применяется метод GetMethods(). Этот метод возвращает все методы типа в виде массива объектов MethodInfo. Его свойства предоставляют информацию о методе. Отметим некоторые из его свойств:

  • IsAbstract: возвращает true, если метод абстрактный

  • IsFamily: возвращает true, если метод имеет модификатор доступа protected

  • IsFamilyAndAssembly: возвращает true, если метод имеет модификатор доступа private protected

  • IsFamilyOrAssembly: возвращает true, если метод имеет модификатор доступа protected internal

  • IsAssembly: возвращает true, если метод имеет модификатор доступа internal

  • IsPrivate: возвращает true, если метод имеет модификатор доступа private

  • IsPublic: возвращает true, если метод имеет модификатор доступа public

  • IsConstructor: возвращает true, если метод предоставляет конструктор

  • IsStatic: возвращает true, если метод статический

  • IsVirtual: возвращает true, если метод виртуальный

  • ReturnType: возвращает тип возвращаемого значения

Некоторые из методов MethodInfo:

  • GetMethodBody(): возвращает тело метода в виде объекта MethodBody

  • GetParameters(): возвращает массив параметров, где каждый параметр представлен объектом типа ParameterInfo

  • Invoke(): вызывает метод

Применим ряд свойств для исследования методов класса:


using System.Reflection;

Type myType = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo method in myType.GetMethods())
{
    string modificator = "";

    // если метод статический
    if (method.IsStatic) modificator += "static ";
    // если метод виртуальный
    if (method.IsVirtual) modificator += "virtual ";

    Console.WriteLine($"{modificator}{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    public string CreateMessage() => DefaultMessage;
}

На выходе получим следующую информацию:


Методы:
String get_DefaultMessage ()
Void set_DefaultMessage ()
Void PrintMessage ()
String CreateMessage ()
Type GetType ()
virtual String ToString ()
virtual Boolean Equals ()
virtual Int32 GetHashCode ()

Как видно из вывода в категорию методов также попадают и свойства, которые по сути представляют два метода: get и set. Если подобная ситуация не устраивает, то можно дополнительно фильтровать список методов:


foreach (MethodInfo method in myType.GetMethods()
            .Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_")))
{
 // .........
}

BindingFlags

В примере выше использовалась простая форма метода GetMethods(), которая извлекает все общедоступные публичные методы. Но мы можем использовать и другую форму метода: MethodInfo[] GetMethods(BindingFlags). Объединяя значения BindingFlags можно комбинировать вывод. Например, получим только методы самого класса без унаследованных, как публичные, так и все остальные:


using System.Reflection;

Type myType = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo method in myType.GetMethods(BindingFlags.DeclaredOnly
            | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
    Console.WriteLine($"{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    protected internal void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    private string CreateMessage() => DefaultMessage;
}

Теперь метод Print в классе Person является приватным, а метод SayMessage имеет модификатор protected internal.

Для получения всех непубличных методов в метод GetMethods() передается набор флагов BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public, то есть получаем все методы экземпляра, как публичные, так и непубличные, но исключаем статические. Соответственно теперь получим следующий вывод:

Методы:
String get_DefaultMessage ()
Void set_DefaultMessage ()
Void PrintMessage ()
String CreateMessage ()

Исследование параметров

С помощью метода GetParameters() можно получить все параметры метода в виде массива объектов ParameterInfo. Отметим некоторые из свойств ParameterInfo, которые позволяют получить информацию о параметрах:

  • Attributes: возвращает атрибуты параметра

  • DefaultValue: возвращает значение параметра по умолчанию

  • HasDefaultValue: возвращает true, если параметр имеет значение по умолчанию

  • IsIn: возвращает true, если параметр имеет модификатор in

  • IsOptional: возвращает true, если параметр является необязательным

  • IsOut: возвращает true, если параметр является выходным, то есть имеет модификатор out

  • Name: возвращает имя параметра

  • ParameterType: возвращает тип параметра

Используем тип ParameterInfo для исследования параметров:


using System.Reflection;

foreach (MethodInfo method in typeof(Printer).GetMethods())
{
    Console.Write($"{method.ReturnType.Name} {method.Name} (");
    //получаем все параметры
    ParameterInfo[] parameters = method.GetParameters();
    for (int i = 0; i < parameters.Length; i++)
    {
        var param = parameters[i];
        // получаем модификаторы параметра
         string modificator = "";
        if (param.IsIn) modificator = "in";
        else if (param.IsOut) modificator = "out";

        Console.Write($"{param.ParameterType.Name} {modificator} {param.Name}");
        // если параметр имеет значение по умолчанию
        if (param.HasDefaultValue) Console.Write($"={param.DefaultValue}");
        // если не последний параметр, добавляем запятую
        if (i < parameters.Length - 1) Console.Write(", ");
    }
    Console.WriteLine(")");
}

class Printer
{
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
     public void CreateMessage(out string message) => message = "Hello Metanit.com";
}

Консольный вывод:

Void PrintMessage (String  message, Int32  times=1)
Void CreateMessage (String& out message)
Type GetType ()
String ToString ()
Boolean Equals (Object  obj)
Int32 GetHashCode ()

Стоит отметить, что если параметр имеет модификатор ref, in, out, то в конце названия типа добавляется амперсанд - String&.

Вызов методов

С помощью метода Invoke() можно вызвать метод:


public object? Invoke (object? obj, object?[]? parameters);

Первый параметр представляет объект, для которого вызывается метод. Второй объект представляет массив значений, которые передаются параметрам метода. И также метод может возвращать результат в виде значения object?.

Вызов метода:


using System.Reflection;

var myPrinter = new Printer("Hello");

// получаем метод Print
var print = typeof(Printer).GetMethod("Print");
// вызываем метод Print
print?.Invoke(myPrinter, parameters: null); // Hello

class Printer
{
    public string Text { get;}
    public Printer(string text) => Text = text;
    public void Print() => Console.WriteLine(Text);
}

Метод GetMethod() возвращает метод, который имеет определенное имя - в данном случае метод Print. Далее используя полученный метод, его можно вызвать. Здесь при вызове в качестве первого параметра передается объект, для которого вызывается метод Print - объект myPrinter. И поскольку метод Print не принимает параметров, параметру parameters передается значение null.

Если метод непубличный, то для получения метода мы можем передать флаги в вызов GetMethod:


using System.Reflection;

var myPrinter = new Printer("Hello METANIT.COM");

// получаем метод Print
var print = typeof(Printer).GetMethod("Print",
            BindingFlags.Instance |
            BindingFlags.Public |
            BindingFlags.NonPublic);
// вызываем метод Print
print?.Invoke(myPrinter, parameters: null); // Hello METANIT.COM

class Printer
{
    public string Text { get;}
    public Printer(string text) => Text = text;
    private void Print() => Console.WriteLine(Text);
}

Получение результата:


using System.Reflection;

var myPrinter = new Printer();
// получаем метод CreateMessage
var createMessage = typeof(Printer).GetMethod("CreateMessage");
// вызываем метод CreateMessage и получаем его результат
var result = createMessage?.Invoke(myPrinter, parameters: null);
Console.WriteLine(result);  // Hello Metanit.com

class Printer
{
    public string CreateMessage() => "Hello Metanit.com";
}

Стоит отметить, что результат метода представляет тип object?, соответственно при необходимости может потребоваться выполнить приведение типов.

Передача параметров:


using System.Reflection;

var myPrinter = new Printer();
// получаем метод PrintMessage
var printMessage = typeof(Printer).GetMethod("PrintMessage");
// вызываем метод PrintMessage, передавая ему два аргумента
printMessage?.Invoke(myPrinter, new object[] {"Hi world", 3});

class Printer
{
    public void PrintMessage(string message, int times)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
}

Здесь метод PrintMessage имеет два параметра - messsage (некоторое соощение) и times (сколько раз надо вывести сообщение на консоль). И для этих параметров передаем массив аргументов new object[] {"Hi world", 3}. Таким образом, метод три раза выведет строку "Hi world".

Вызов обобщенного метода:


using System.Reflection;

var myPrinter = new Printer();
// получаем метод PrintValue
var printValue = typeof(Printer).GetMethod("PrintValue");
// получаем обобщенную версию метода для типа string
var printStringValue = printValue?.MakeGenericMethod(typeof(string));
// вызываем метод PrintValue, передавая ему строку
printStringValue?.Invoke(myPrinter, new object[] {"Hello world"});

class Printer
{
    public void PrintValue<T>(T value)
    {
        Console.WriteLine(value);
    }
}

Для получения обобщенной версии метода, которая типизирована определенным типом, у объекта MethodInfo вызывается метод MakeGenericMethod - в него передает тип, которым типизируется метод.

Получение конструкторов

Для получения конструкторов применяется метод GetConstructors(), который возвращает массив объектов класса ConstructorInfo. Этот класс во многом похож на MethodInfo и имеет ряд общей функциональности. Некоторые основные свойства и методы:

  • Свойство IsFamily: возвращает true, если конструктор имеет модификатор доступа protected

  • Свойство IsFamilyAndAssembly: возвращает true, если конструктор имеет модификатор доступа private protected

  • Свойство IsFamilyOrAssembly: возвращает true, если конструктор имеет модификатор доступа protected internal

  • Свойство IsAssembly: возвращает true, если конструктор имеет модификатор доступа internal

  • Свойство IsPrivate: возвращает true, если конструктор имеет модификатор доступа private

  • Свойство IsPublic: возвращает true, если конструктор имеет модификатор доступа public

  • Метод GetMethodBody(): возвращает тело конструктора в виде объекта MethodBody

  • Метод GetParameters(): возвращает массив параметров, где каждый параметр представлен объектом типа ParameterInfo

  • Метод Invoke(): вызывает конструктор

Исследуем конструкторы


using System.Reflection;

Type myType = typeof(Person);

Console.WriteLine("Конструкторы:");
foreach (ConstructorInfo ctor in myType.GetConstructors(
    BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
    string modificator = "";

    // получаем модификатор доступа
    if (ctor.IsPublic)
        modificator += "public";
    else if (ctor.IsPrivate)
        modificator += "private";
    else if (ctor.IsAssembly)
        modificator += "internal";
    else if (ctor.IsFamily)
        modificator += "protected";
    else if (ctor.IsFamilyAndAssembly)
        modificator += "private protected";
    else if (ctor.IsFamilyOrAssembly)
        modificator += "protected internal";

    Console.Write($"{modificator} {myType.Name}(");
    // получаем параметры конструктора
    ParameterInfo[] parameters = ctor.GetParameters();
    for (int i = 0; i < parameters.Length; i++)
    {
        var param = parameters[i];
        Console.Write($"{param.ParameterType.Name} {param.Name}");
        if (i < parameters.Length - 1) Console.Write(", ");
    }
    Console.WriteLine(")");
}
class Person
{
    public string Name { get; }
    public int Age { get; }
    public Person(string name, int age)
    {
        Name = name; Age = age;
    }
    public Person(string name) : this(name, 1) { }
    private Person() : this("Tom") { }
}

В данном случае исследуем конструкторы класса Person, один из которых является приватным. Консольный вывод:

Конструкторы:
public Person(String name, Int32 age)
public Person(String name)
private Person()

Проверь себя

📋 Тест по теме «Исследование методов и конструкторов с помощью рефлексии» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

using _____.Reflection;

Type myType = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo method in myType.GetMethods())
{
    string modificator = "";

    // если метод статический
    if (method.IsStatic) modificator += "static ";
    // если метод виртуальный
    if (method.IsVirtual) modificator += "virtual ";

    Console.WriteLine($"{modificator}{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    public string CreateMessage() => DefaultMessage;
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

Методы:
String get_DefaultMessage ()
Void _____ ()
Void PrintMessage ()
String CreateMessage ()
Type GetType ()
virtual String ToString ()
virtual Boolean Equals ()
virtual Int32 GetHashCode ()
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

foreach (MethodInfo _____ in myType.GetMethods()
            .Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_")))
{
 // .........
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

using System.Reflection;

Type _____ = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo method in myType.GetMethods(BindingFlags.DeclaredOnly
            | BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public))
{
    Console.WriteLine($"{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    protected internal void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    private string CreateMessage() => DefaultMessage;
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

using System.Reflection;

foreach (MethodInfo _____ in typeof(Printer).GetMethods())
{
    Console.Write($"{method.ReturnType.Name} {method.Name} (");
    //получаем все параметры
    ParameterInfo[] parameters = method.GetParameters();
    for (int i = 0; i < parameters.Length; i++)
    {
        var param = parameters[i];
        // получаем модификаторы параметра
         string modificator = "";
        if (param.IsIn) modificator = "in";
        else if (param.IsOut) modificator = "out";

        Console.Write($"{param.ParameterType.Name} {modificator} {param.Name}");
        // если параметр имеет значение по умолчанию
        if (param.HasDefaultValue) Console.Write($"={param.DefaultValue}");
        // если не последний параметр, добавляем запятую
        if (i < parameters.Length - 1) Console.Write(", ");
    }
    Console.WriteLine(")");
}

class Printer
{
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
     public void CreateMessage(out string message) => message = "Hello Metanit.com";
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

using System.Reflection;

Type myType = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo _____ in myType.GetMethods())
{
    string modificator = "";

    // если метод статический
    if (_____.IsStatic) modificator += "static ";
    // если метод виртуальный
    if (method.IsVirtual) modificator += "virtual ";

    Console.WriteLine($"{modificator}{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    public string CreateMessage() => DefaultMessage;
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

Методы:
String get_DefaultMessage ()
Void _____ ()
Void PrintMessage ()
String CreateMessage ()
Type GetType ()
_____ String ToString ()
virtual Boolean Equals ()
virtual Int32 GetHashCode ()
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

foreach (MethodInfo method in myType.GetMethods()
            .Where(m => !m.Name.StartsWith("get_") && !m.Name.StartsWith("set_")))
{
}
 // .........
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Исследование методов и конструкторов с помощью рефлексии»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Исследование методов и конструкторов с помощью рефлексии», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

using System.Reflection;

Type myType = typeof(Printer);

Console.WriteLine("Методы:");
foreach (MethodInfo method in myType.GetMethods())
{
    string modificator = "";

    // если метод статический
    if (method.IsStatic) modificator += "static ";
    // если метод виртуальный
    if (method.IsVirtual) modificator += "virtual ";

    Console.WriteLine($"{modificator}{method.ReturnType.Name} {method.Name} ()");
}
class Printer
{
    public string DefaultMessage { get; set; } = "Hello";
    public void PrintMessage(string message, int times = 1)
    {
        while (times-- > 0) Console.WriteLine(message);
    }
    public string CreateMessage() => DefaultMessage;
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Исследование методов и конструкторов с помощью рефлексии»
+30 XP

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

Методы:
String get_DefaultMessage ()
Void set_DefaultMessage ()
Void PrintMessage ()
String CreateMessage ()
Type GetType ()
virtual String ToString ()
virtual Boolean Equals ()
virtual Int32 GetHashCode ()
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Исследование методов и конструкторов с помощью рефлексии»
+50 XP

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

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Исследование методов и конструкторов с помощью рефлексии»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Исследование методов и конструкторов с помощью рефлексии». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.