Отражение (reflection)
Сборка и метаданные
Метаданные
Метаданные -2
Класс System.Type
Некоторые свойства, определенные в классе System.Type
Некоторые методы, определенные в классе System.Type
Как получить значение поля?
Вызов метода по ссылке на объект System.Type
Атрибуты
Пользовательские атрибуты
Пример определения нового атрибута
Атрибут AttributeUsage
Перечисление AttributeTargets
Использование нового атрибута
Атрибут FlagsAttribute
Атрибут ConditionalAttribute - условная компиляция
Атрибут ConditionalAttribute - 2
Атрибут ConditionalAttribute - пример
302.50K
Category: programmingprogramming

Отражение (reflection). Лекция 5

1. Отражение (reflection)

Отражение – получение из метаданных информации о типах,
определенных в сборке.
Классы, поддерживающие механизм отражения, находятся в
пространстве имен System.Reflection.
Класс System.Type – абстрактный класс для хранения
информации о типе.
Схема наследования для класса System.Type:
System.Object
System.Reflection.MemberInfo
System.Type

2. Сборка и метаданные

• Сборка - исполняемое под
управлением CLR приложение
или библиотека с типами и/или
ресурсами.
• Метаданные содержат
описание всех типов,
определенных в приложении.
Рисунок из MSDN
Developer Tools \ Visual Studio 2008 \ Visual Studio \
Visual C# \ Getting Started with Visual C# \
Introduction to the C# Language and .NET Framework
• Можно программно получить
всю информацию о сборке,
используя механизм отражения
(reflection).

3. Метаданные

Метаданные – это бинарная информация, которая добавляется в PEфайл (portable executable file) при компиляции исходного кода в MSIL.
При выполнении кода CLR загружает метаданные в память.
Метаданные содержат полную информацию о сборке.
• Описание сборки.
• Имя, версия, региональные стандарты (culture), ключ издателя
(public key).
• Типы, определенные в сборке.
• Другие сборки, на которые ссылается данная сборка.
• Права (security permissions), необходимые для выполнения сборки.
• Описание каждого типа, определенного в приложении.
• Имя, видимость, базовый класс, реализованные интерфейсы.
• Члены класса (методы, свойства, поля, события, вложенные типы).
• Атрибуты – дополнительную декларативную информацию.

4. Метаданные -2

Метаданные используются
• Сборщиком мусора
• При сериализации объекта
• VisualStudio для подсказок при написании
исходного кода
Метаданные доступны через
• Методы классов, поддерживающих механизм
отражения (reflection)
• ILDASM

5. Класс System.Type

В классе System.Type определено более 100 свойств и методов,
которые дают возможность получить полную информацию о типе.
Объект типа System.Type, предоставляющий информацию о типе,
уникален. Ссылку на объект System.Type для конкретного типа можно
получить многими способами, но все ссылки на этот объект будут
равны.
Student st = new Student();
Type t1 = typeof(Student);
Type t2 = st.GetType();
Console.WriteLine(object.ReferenceEquals(t1, t2)); // true
Console.WriteLine("\ntypeof(Student) {0}", t1.FullName);

6. Некоторые свойства, определенные в классе System.Type

public abstract class Type : MemberInfo, IReflect
{
public abstract Assembly Assembly {get;} // сборка, в которой определен
// тип
public TypeAttributes Attributes {get;}
// атрибуты, связанные с типом
public abstract Type BaseType {get;}
// ссылка на базовый тип
public abstract string FullName {get;}
public bool IsSerializable {get;}
public bool IsValueType {get;}
public bool IsClass {get;}

}

7. Некоторые методы, определенные в классе System.Type

public FieldInfo[ ] GetFields(); // информация об открытых полях типа;
// есть перегруженная версия с возможностью настройки
// на поля с другим типом доступа;
public MethodInfo[ ] GetMethods();
public PropertyInfo[ ] GetProperties();
public abstract object[ ] GetCustomAttributes( bool inherit );
Типы FieldInfo, MethodInfo, PropertyInfo определены в пространстве
имен System.Reflection и имеют свойства и методы для получения
более детальной информации.

8. Как получить значение поля?

Метод класса FieldInfo
public abstract object GetValue( object obj );
дает возможность передать ссылку на инициализированный объект
типа и получить значение поля. Например,
Type tp = typeof(Student);
Student stest = new Student();
FieldInfo[] flds = tp.GetFields();
if (flds.Length == 0) Console.WriteLine("\nNo public fields");
else
{ foreach (FieldInfo item in flds)
{
Console.Write(item.Name);
Console.Write("
" + item.FieldType);
Console.Write("
" + item.IsPrivate);
object s = item.GetValue(stest);
Console.Write("
}
}
" + s.ToString());

9. Вызов метода по ссылке на объект System.Type

Метод класса MethodInfo
public object Invoke( object obj, object[] parameters );
дает возможность передать ссылку на инициализированный объект и
значения параметров и выполнить метод. Например,
Type tp = typeof(Student);
Student stest = new Student();
MethodInfo[] mds = tp.GetMethods();
foreach (MethodInfo item in mds)
{
Console.Write(item.Name);
if (item.Name == "get_Group")
{
object[] parms = null;
object ret = item.Invoke(stest, parms);
Console.Write("
}
}
" + ret);

10. Атрибуты

В C# атрибуты используются для передачи декларативной
информации от разработчика фрагментам кода. При компиляции эта
информация добавляется к метаданным.
Атрибуты
• предопределенные (из BCL)
• пользовательские (custom)
В период выполнения атрибуты доступны с помощью механизма
отражения (reflection).
В C# атрибут размещается перед элементом, к которому он
прикреплен.
Следующие объявления эквивалентны
[FlagsAttribute][SerializableAttribute]
[Serializable][Flags]
[Flags,Serializable]

11. Пользовательские атрибуты

Пользовательский атрибут определяется путем определения класса,
производного от System.Attribute.
Атрибут может иметь позиционные и именованные параметры.
Позиционные параметры
• являются обязательными и указываются при каждом
использовании атрибута;
• порождаются конструкторами с типом доступа public.
Именованные параметры
• не являются обязательными;
• значение параметра указывается вместе с именем параметра;
• всегда располагаются за позиционными;
• порождаются открытыми нестатическими полями и свойствами
класса;
Типами параметров атрибута могут быть только встроенные типы и
одномерные sz-массивы этих типов.
Значениями параметров могут быть только константные выражения.

12. Пример определения нового атрибута

[AttributeUsage(AttributeTargets.Class)]
public class MyCommentAttribute : Attribute
{
string last_update;
string comment;
public
MyCommentAttribute(string last_update)
{
this.last_update = last_update; }
public string Comment
{
get { return comment;}
set { comment = value;}
}
}

13. Атрибут AttributeUsage

Используется только при определении классов атрибутов и может
быть прикреплен только к классу, производному от System.Attribute.
Параметры
Позиционный – комбинация значений перечисления AttributeTargets
( определяет элементы, с которыми можно связать атрибут);
Именованные
• bool AllowMultiple; – запрещает или разрешает
многократное прикрепление к одному элементу ( умолчание
false );
• bool Inherited; – наследуется производным классом, если
прикреплен к базовому ( умолчание true).
Если при объявлении класса атрибута, атрибут AttributeUsage не
указан, значение позиционного параметра считается равным
AttributeTargets.All.

14. Перечисление AttributeTargets

[SerializableAttribute]
[FlagsAttribute]
[ComVisibleAttribute(true)]
public enum AttributeTargets
Перечисление определяет элементы, с которыми можно связать
атрибут.
Элементы перечисления:
All
Assembly
Class
Constructor
Delegate
Enum
Event
Field
GenericParameter
Interface
Method
Module
Parameter
Property
ReturnValue
Struct
Значения перечисления можно комбинировать с помощью побитовой
операци OR.

15. Использование нового атрибута

Объявляем класс и указываем атрибут
[MyComment(“27.10.08", Comment = "Class from Attributes_Demo")]
[Serializable]
public class Abc { …}
Список атрибутов получаем при помощи метода GetCustomAttributes().
Значение true для второго параметра указывает, что атрибут может быть
унаследован от базового класса.
MemberInfo info = typeof (Abc);
object [] ats1 =
info.GetCustomAttributes(typeof(MyCommentAttribute),true);

16. Атрибут FlagsAttribute

Атрибут Flags может быть прикреплен только к перечислению.
[AttributeUsage(AttributeTargets.Enum)]
[Serializable]
public class FlagsAttribute : Attribute
Атрибут указывает, что
• перечисление можно рассматривать как набор битовых
флагов;
• значения перечисления можно комбинировать с помощью
побитовой операци OR.
Примеры:
[Flags]
[Serializable]
public enum FileAccess
[Flags]
[Serializable]
public enum AttributeTargets

17. Атрибут ConditionalAttribute - условная компиляция

При помощи атрибута Conditional можно включать/выключать
вызовы метода на этапе компиляции
[AttributeUsage(AttributeTargets.Method)]
[Serializable]
public sealed class ConditionalAttribute : Attribute
Параметр конструктора атрибута определяет символ (строку)
условной компиляции:
public ConditionalAttribute( string conditionString );
Символ (строка) условной компиляции чувствителен к регистру.
DEBUG и Debug – разные символы.
Атрибут Conditional используется в методах классов Debug и Trace.
Visual Studio определяет символ TRACE для Release-компиляции.
Visual Studio определяет символы TRACE и DEBUG для Debugкомпиляции.

18. Атрибут ConditionalAttribute - 2

Вызов условного метода зависит от того, определен или нет символ
условной компиляции (строка атрибута) в точке вызова метода.
Если символ не определен, то не вычисляются параметры метода и
вызов не включается в код.
Ограничения на метод, к которому может быть прикреплен атрибут:
• метод класса или струтуры (но не интерфейса);
• возвращаемое значение должно быть void;
• метод не имеет модификатор override, но может иметь
модификатор virtual; переопределенные версии этого метода
(overrides) неявно получают атрибут Conditional;
• метод не может быть реализацией интерфейсного метода;
• нельзя использовать метод с атрибутом Conditional в delegatecreation-expression.
Атрибут Conditional допускает многократное прикрепление (multiuse
attribute ).
Вызов метода включается в код, если определен хотя бы один из
прикрепленных к методу символов условной компиляции.

19. Атрибут ConditionalAttribute - пример

File Class1.cs
Метод F класса Abc определен
с атрибутом Conditional.
Символ FAbc не определен.
using System;
using System.Diagnostics;
namespace Conditional_Demo
{ class Class1 {
static void Main(string[] args)
{ Abc abc = new Abc();
abc.F();
Console.WriteLine (“1”);
Class2 cl2= new Class2();
cl2.F2();
}
}
class Abc
{ [Conditional("FAbc")]
public void F()
{Console.WriteLine("Abc.F"); }
}}
File Class2.cs.
Символ FAbc определен.
#define FAbc
using System;
namespace Conditional_Demo
{ public class Class2 {
public void F2()
{ Abc abc = new Abc();
abc.F();
}
}}
Вывод:
1
Abc.F
English     Русский Rules