Similar presentations:
Отражение (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. Как получить значение поля?
Метод класса FieldInfopublic 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
Метод класса MethodInfopublic 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