Рефлексія. Приклади отримання інформації про методи, інтерфейси, класи, структури, зчислення, делегати, поля типів, параметри методів, статистичні дані про типи
Зміст
- 1. Що собою представляє метод System.Type.GetType()?
- 2. Що таке рефлексія методів? Як отримати інформацію про методи? Приклад рефлексії методів
- 3. Як отримати інформацію про поля класу, структури чи зчислення? Приклади рефлексії полів і властивостей
- 4. Як отримати інформацію про інтерфейси, які реалізує клас? Приклад рефлексії інтерфейсів
- 5. Приклад використання рефлексії для отримання додаткових відомостей про тип (клас, структуру, зчислення)
- 6. Як отримати інформацію про властивості (properties) класу? Приклад
- 7. Приклад використання рефлексії для отримання інформації про параметри методу
- Зв’язані теми
Пошук на інших ресурсах:
1. Що собою представляє метод System.Type.GetType()?
Метод System.Type.GetType() призначений для отримання екземпляру типу, що задається параметром. Параметр методу є типу string. Параметр вказує назву типу, для якого потрібно отримати інформацію. Взагалі, метод System.Type.GetType() має 7 перевантажених реалізацій.
Щоб отримати перелік методів деякого типу (наприклад, класу) потрібно спочатку отримати об’єкт, що містить інформацію про тип. Це здійснюється з допомогою методу
GetType("NameSpace.TypeName")
де
- NameSpace – назва простору імен, в якому розміщується тип з іменем TypeName, який потребує дослідження;
- TypeName – назва типу, про який потрібно отримати інформацію. Типом може бути клас, структура, інтерфейс, зчислення, делегат.
Наприклад
Type tp = Type.GetType("Dates.Date");
У цьому прикладі створюється екземпляр (об’єкт) з іменем tp, що містить інформацію про тип з іменем Date, який оголошено у просторі імен Dates.
⇑
2. Що таке рефлексія методів? Як отримати інформацію про методи? Приклад рефлексії методів
Рефлексія методів дозволяє отримати інформацію про перелік загальнодоступних (public) методів з заданого типу.
Інформацію про методи можна отримувати для класу, структури чи інтерфейсу. Тільки ці типи можуть містити оголошення методів.
Щоб отримати перелік методів заданого екземпляру типу, потрібно викликати метод GetMethods(), що повертає масив типу MethodInfo, який містить усю необхідну інформацію про методи.
Приклад. Задано клас Date, що описує дату. У класі реалізовано 3 внутрішні змінні та 6 методів доступу до них. Нижче наведено текст програми, що демонструє рефлексію методів. Програма створена за шаблоном Console Application.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace ConsoleApp2 { // клас, що описує дату public class Date { int number; int month; int year; // методи доступу public int GetNumber() { return number; } public int GetMonth() { return month; } public int GetYear() { return year; } public void SetNumber(int nnumber) { number = nnumber; } public void SetMonth(int nmonth) { month = nmonth; } public void SetYear(int nyear) { year = nyear; } } class Program { static void Main(string[] args) { // отримати інформацію про методи // отримати екземпляр типу за його іменем Type tp = Type.GetType("ConsoleApp2.Date"); // назва класу - "Date" у збірці ConsoleApp2 // отримати масив методів класу Date MethodInfo[] methods = tp.GetMethods(); // вивести назви методів на екран int i = 0; foreach (MethodInfo mi in methods) { i++; Console.WriteLine("Method[{0}] = {1}", i, mi.Name); } } } }
У результаті виконання даного коду, на екран буде виведено перелік назв методів, що доступні для будь-якого об’єкту класу Date:
Method[1] = GetNumber Method[2] = GetMonth Method[3] = GetYear Method[4] = SetNumber Method[5] = SetMonth Method[6] = SetYear Method[7] = ToString Method[8] = Equals Method[9] = GetHashCode Method[10] = GetType Press any key to continue . . .
Слід зауважити наступне:
- отримується інформація тільки про ті методи, які оголошені як загальнодоступні з модифікатором доступу public;
- щоб отримати екземпляр типу методом GetType() зі статичної функції Main(), обов’язково потрібно перед іменем класу вказувати назву простору імен в якому цей клас реалізований.
⇑
3. Як отримати інформацію про поля класу, структури чи зчислення? Приклади рефлексії полів і властивостей
Щоб отримати інформацію про поле (властивість) деякого типу (клас, структура, зчислення), потрібно використати метод Type.GetFields(). Цей метод повертає масив типу FieldInfo. Тип FieldInfo містить усю необхідну інформацію про поля та властивості, які оголошені як public.
Приклад 1. Отримання інформації про поля структури. Задано структуру Worker. У структурі реалізовано 3 поля з іменами name, age, rank. У прикладі демонструється виведення інформації про назву поля та його тип (властивість FieldType). Приклад реалізований як консольний додаток
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { // структура, що реалізує інформацію про працівника public struct Worker { public static string name; // ім'я працівника public int age; // вік працівника public float rank; // рейтинг працівника } class Program { static void Main(string[] args) { // отримати інформацію про поля структури Worker // створити об'єкт, що містить інформацію про структуру Worker Type tp = Type.GetType("TrainReflection.Worker"); // отримати інформацію про поля структури Worker FieldInfo[] fields = tp.GetFields(); // вивести назви полів, їх типи та деякі атрибути int i = 0; string nameType; foreach (var field in fields) { i++; nameType = field.FieldType.ToString(); // отримати назву типу поля field структури Worker Console.Write("Field[{0}] = {1}, type = {2}", i, field.Name, nameType); // перевірка, чи поле статичне if (field.IsStatic) Console.Write(", static"); // перевірка, чи поле оголошене як public if (field.IsPublic) Console.Write(", public"); Console.WriteLine(); } } } }
У результаті, на екран буде виведено наступний текст:
Field[1] = age, type = System.Int32, public Field[2] = rank, type = System.Single, public Field[3] = name, type = System.String, static, public Press any key to continue . . .
Таким самим чином можна отримати інформацію про поля будь-якого класу будь-якої збірки. Достатньо знати тільки ім’я класу в збірці.
Приклад 2. Отримання інформації про поля зчислення. Задано зчислення Month, що реалізує скорочені назви місяців року. Нижче наведено приклад отримання інформації про зчислення на основі інформації про його ім’я.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { // зчислення, що реалізує інформацію про місяць року enum Month { Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec } class Program { static void Main(string[] args) { // отримати інформацію про поля зчислення Month // створити об'єкт, що містить інформацію про структуру Worker Type tp = Type.GetType("TrainReflection.Month"); // отримати інформацію про поля зчислення Month FieldInfo[] fields = tp.GetFields(); // вивести назви полів зчислення enum int i = 0; string value; foreach (var field in fields) { i++; Console.WriteLine("Field[{0}] = {1}", i, field.Name); } } } }
У результаті, на екран буде виведено наступний текст
Field[1] = value__ Field[2] = Jan Field[3] = Feb Field[4] = Mar Field[5] = Apr Field[6] = May Field[7] = Jun Field[8] = Jul Field[9] = Aug Field[10] = Sep Field[11] = Oct Field[12] = Nov Field[13] = Dec Press any key to continue . . .
⇑
4. Як отримати інформацію про інтерфейси, які реалізує клас? Приклад рефлексії інтерфейсів
Щоб отримати перелік імен інтерфейсів, які підтримуються заданим типом, використовується метод GetInterfaces(). Цей метод повертає масив інтерфейсів типу Type[].
Назва інтерфейсу міститься у властивості Name.
Приклад. Нехай задано інтерфейс IDate, в якому оголошуються імена двох методів: GetNumber(), SetNumber(). Також оголошується клас Date, який реалізує дату. Клас Date успадковує інтерфейс IDate. У прикладі продемонстровано:
- отримання переліку інтерфейсів класу Date;
- отримання переліку методів інтерфейсу IDate.
Повний лістинг програми, що демонструє даний приклад
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { // інтерфейс з оголошеними двома методами interface IDate { int GetNumber(); void SetNumber(int nnumber); } // клас, що описує дату - успадковує інтерфейс IDate public class Date:IDate { int number; int month; int year; // методи доступу public int GetNumber() { return number; } public int GetMonth() { return month; } public int GetYear() { return year; } public void SetNumber(int nnumber) { number = nnumber; } public void SetMonth(int nmonth) { month = nmonth; } public void SetYear(int nyear) { year = nyear; } } class Program { static void Main(string[] args) { // отримати інформацію про методи // отримати екземпляр типу за його іменем Type tp = Type.GetType("TrainReflection.Date"); // назва класу - "Date" // отримати масив інтерфейсів класу Date Type[] interfaces = tp.GetInterfaces(); // вивести назви інтерфейсів класу Date на екран int i = 0; foreach (Type t in interfaces) { i++; Console.WriteLine("Interface[{0}] = {1}", i, t.Name); } Console.WriteLine(); // створити об'єкт, що містить інформацію про інтерфейс IDate Type tpi = Type.GetType("TrainReflection.IDate"); // отримати масив методів для інтерфейсу IDate з допомогою об'єкту tpi MethodInfo[] methods = tpi.GetMethods(); // вивести перелік методів інтерфейсу IDate i = 0; foreach (MethodInfo mt in methods) { i++; // вивести повне ім'я кожного методу інтерфейсу Console.WriteLine("Method[{0}] = {1}", i, mt.Name); } } } }
У результаті виконання програми на екран буде виведено:
Interface[1] = IDate Method[1] = GetNumber Method[2] = SetNumber Press any key to continue . . .
⇑
5. Приклад використання рефлексії для отримання додаткових відомостей про тип (клас, структуру, зчислення)
З допомогою рефлексії можна отримувати додаткові відомості про тип. Типом може бути клас, структура, інтерфейс, зчислення, делегат.
Приклад. Нехай задано два класи:
- клас Point, що реалізує точку на координатній площині;
- клас Pixel, що реалізує точку з заданим кольором. Клас Pixel є успадкованим з класу Point.
Нижче наводиться повний текст програми, що виводить додаткові відомості про класи Point та Pixel. Програма реалізована як додаток типу Console Application.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { public class Point { // внутрішні змінні класу protected int x; protected int y; // методи доступу public void GetXY(out int xx, out int yy) { xx = x; yy = y; } public void SetXY(int xx, int yy) { x = xx; y = yy; } } // клас Pixel є похідним від класу Point sealed class Pixel:Point { // внутрішня змінна color int color; // методи доступу public void GetXYC(out int xx, out int yy, out int cl) { GetXY(out xx, out yy); cl = color; } public void SetXYC(int xx, int yy, int cl) { SetXY(xx, yy); color = cl; } } class Program { static void Main(string[] args) { // створити об'єкти для класів Point та Pixel Type tPoint = Type.GetType("TrainReflection.Point"); Type tPixel = Type.GetType("TrainReflection.Pixel"); // вивести деяку інформацію про клас Point Console.WriteLine("Information about Point class:"); if (tPoint.IsAbstract) Console.WriteLine("Abstract class"); // абстрактний клас if (tPoint.IsArray) Console.WriteLine("Array"); // це є масив if (tPoint.IsClass) Console.WriteLine("Class or delegate"); // це є клас або делегат if (tPoint.IsEnum) Console.WriteLine("Enumeration"); // це є зчислення if (tPoint.IsInterface) Console.WriteLine("Interface"); // це є інтерфейс if (tPoint.IsPublic) Console.WriteLine("Public"); // оголошений як public if (tPoint.IsSealed) Console.WriteLine("Sealed"); // запечатаний Console.WriteLine(); // вивести деяку інформацію про клас Pixel Console.WriteLine("Information about Pixel class:"); if (tPixel.IsAbstract) Console.WriteLine("Abstract class"); // абстрактний клас if (tPixel.IsArray) Console.WriteLine("Array"); // це є масив if (tPixel.IsClass) Console.WriteLine("Class or delegate"); // це є клас або делегат if (tPixel.IsEnum) Console.WriteLine("Enumeration"); // це є зчислення if (tPixel.IsInterface) Console.WriteLine("Interface"); // це є інтерфейс if (tPixel.IsPublic) Console.WriteLine("Public"); // оголошений як public if (tPixel.IsSealed) Console.WriteLine("Sealed"); // запечатаний } } }
У результаті виконання програми, на екран буде виведено наступне:
Information about Point class: Class or delegate Public Information about Pixel class: Class or delegate Sealed Press any key to continue . . .
⇑
6. Як отримати інформацію про властивості (properties) класу? Приклад
Щоб отримати інформацію про властивості класу потрібно викликати метод GetProperties(). Цей метод повертає масив типу PropertyInfo[]. Масив PropertyInfo[] містить відомості про властивості (properties) класу.
Приклад. Продемонстровано отримання переліку властивостей для класу Student з простору імен TrainReflection. Властивості обов’язково мають бути оголошені з модифікатором доступу public.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { // інформація про студента class Student { string name; // ім'я студента string numBook; // номер залікової float rank; // рейтинг студента // властивості public string Name { get { return name; } set { name = value; } } public string NumBook { get { return numBook; } set { numBook = value; } } public float Rank { get { return rank; } set { rank = value; } } } class Program { static void Main(string[] args) { // отримати інформацію про властивості з класу Student // отримати об'єкт типу System.Type Type tp = Type.GetType("TrainReflection.Student"); // отримати перелік властивостей PropertyInfo[] properties = tp.GetProperties(); // вивести перелік властивостей int i = 0; foreach (PropertyInfo p in properties) { i++; Console.WriteLine("Property[{0}] = {1}", i, p.Name); } } } }
На екран буде виведено наступний текст
Property[1] = Name Property[2] = NumBook Property[3] = Rank Press any key to continue . . .
⇑
7. Приклад використання рефлексії для отримання інформації про параметри методу
Для конкретного методу можна отримати інформацію про його параметри.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; // підключити System.Reflection using System.Reflection; namespace TrainReflection { // клас, що містить математичні функції class MathFunctions { // метод, що розв'язує квадратне рівняння public bool CalcEquation(double a, double b, double c, out double x1, out double x2) { double d = b * b - 4 * a * c; if (a==0) { if (b==0) { x1 = x2 = 0; return false; } else { x1 = x2 = -c / b; return true; } } if (d<0) { x1 = x2 = 0; return false; } x1 = (-b - Math.Sqrt(d)) / (2 * a); x2 = (-b + Math.Sqrt(d)) / (2 * a); return true; } } class Program { static void Main(string[] args) { // отримати інформацію про властивості з класу Student // отримати об'єкт типу System.Type Type tp = Type.GetType("TrainReflection.MathFunctions"); // отримати об'єкт, що містить інформацію про конкретний метод CalcEquation класу MathFunctions MethodInfo method = tp.GetMethod("CalcEquation"); // отримати параметри методу CalcEquation ParameterInfo[] parameters = method.GetParameters(); // вивести параметри методу Console.WriteLine("Parameters of method CalcEquation:"); int i = 0; foreach (ParameterInfo p in parameters) { i++; Console.WriteLine("Parameter[{0}] = {1} of type {2}", i, p.Name, p.ParameterType.Name); } // вивести тип значення, що повертається методом string returnType = method.ReturnType.FullName; Console.WriteLine(); Console.WriteLine("The returned type: {0}", returnType); } } }
Вивід на екран буде наступним
Parameters of method CalcEquation: Parameter[1] = a of type Double Parameter[2] = b of type Double Parameter[3] = c of type Double Parameter[4] = x1 of type Double& Parameter[5] = x2 of type Double& The returned type: System.Boolean Press any key to continue . . .
⇑
Зв’язані теми
- Динамічна ідентифікація типів. Оператори is, as. Приклади
- Рефлексія типів. Отримання метаданих типу. Простір імен System.Reflection. Клас System.Type. Способи отримання інформації про тип
- Динамічно завантажувані збірки. Клас Assembly. Методи Load() та LoadFrom()