Скачать презентацию Отражение reflection ü Отражение получение из метаданных Скачать презентацию Отражение reflection ü Отражение получение из метаданных

11_C#_отражение_атрибуты.pptx

  • Количество слайдов: 19

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

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

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

Класс System. Type ü В классе System. Type определено более 100 свойств и методов, Класс System. Type ü В классе System. Type определено более 100 свойств и методов, которые дают возможность получить полную информацию о типе. ü Объект типа System. Type, предоставляющий информацию о типе, уникален. Ссылку на объект System. Type для конкретного типа можно получить многими способами, но все ссылки на этот объект будут равны. Person ps = new Person("Иван", "Иванов", new Date. Time(1989, 1, 1)); Person st = new Student("Николай", "Николаев", new Date. Time(1990, 9, 9), 301, 4. 9); Type type_person = typeof(Person); Type type_ps = ps. Get. Type(); Type type_st = st. Get. Type(); Console. Write. Line(object. Reference. Equals(type_person, type_ps)); // true Console. Write. Line(type_ps. Full. Name); Console. Write. Line(type_st. Full. Name); Console. Write. Line(type_ps. Base. Type. Full. Name); Console. Write. Line(type_st. Base. Type); Вывод : (классы Person и Student определены в пространстве имен PS_Library) True PS_Library. Person PS_Library. Student System. Object PS_Library. Person

Некоторые свойства, определенные в классе System. Type public abstract class Type : Member. Info, Некоторые свойства, определенные в классе System. Type public abstract class Type : Member. Info, IReflect { public abstract Assembly {get; } // сборка, в которой определен // тип public Type. Attributes {get; } // атрибуты, связанные с типом public abstract Type Base. Type {get; } // ссылка на базовый тип public abstract string Full. Name {get; } public bool Is. Serializable {get; } public bool Is. Value. Type {get; } public bool Is. Class {get; } … }

Некоторые методы, определенные в классе System. Type public Field. Info[ ] Get. Fields(); // Некоторые методы, определенные в классе System. Type public Field. Info[ ] Get. Fields(); // информация об открытых полях типа; // есть перегруженная версия с возможностью настройки // на поля с другим типом доступа; public Method. Info[ ] Get. Methods(); public Property. Info[ ] Get. Properties(); public abstract object[ ] Get. Custom. Attributes( bool inherit ); ü Типы Field. Info, Method. Info, Property. Info определены в пространстве имен System. Reflection и имеют свойства и методы для получения более детальной информации.

Как получить значение поля? ü Метод класса Field. Info public abstract object Get. Value( Как получить значение поля? ü Метод класса Field. Info public abstract object Get. Value( object obj ); дает возможность передать ссылку на инициализированный объект типа и получить значение поля. Type type_st = typeof(Student); Student stest = new Student("Федор", "Федоров", new Date. Time(1991, 3, 3), 303, 3. 3); Field. Info[] flds = type_st. Get. Fields(Binding. Flags. Instance | Binding. Flags. Non. Public); if (flds. Length == 0) Console. Write. Line("n. No private & protected fields in PS_Library. Student"); else { foreach (Field. Info item in flds) { Console. Write(item. Name); Console. Write(" " + item. Field. Type); Console. Write(" " + item. Is. Private); object s = item. Get. Value(stest); Console. Write(" " + s. To. String() + “n”); } } Вывод : group System. Int 32 True 303 ball System. Double True 3, 3

Вызов метода по ссылке на объект System. Type ü Метод класса Method. Info public Вызов метода по ссылке на объект System. Type ü Метод класса Method. Info public object Invoke( object obj, object[] parameters ); дает возможность передать ссылку на инициализированный объект и значения параметров и выполнить метод. Type type_st = typeof(Student); Student stest = new Student("Федор", "Федоров", new Date. Time(1991, 3, 3), 303, 3. 3); Method. Info[] methods = type_st. Get. Methods(); foreach (Method. Info item in methods) { Console. Write(item. Name); } if ( item. Name == "get_Group" || item. Name == "get_Ball") { Console. Write(" " + item. Invoke(stest, null)); } if ( item. Name == "Compare") { object[] parms = { new Person(), new Person("A", "B", Date. Time. Today)}; Console. Write(" " + item. Invoke(stest, parms)); } Console. Write. Line(); Вывод : To. String To. Short. String get_Group 303 set_Group get_Ball 3, 3 set_Ball get_Names set_Names Equals Get. Hash. Code Compare -1 Compare. To Get. Type

Информация о сборке ü Свойство Assembly класса Type возвращает ссылку на объект типа Assembly Информация о сборке ü Свойство Assembly класса Type возвращает ссылку на объект типа Assembly с информацией о сборке, в которой определен тип. public abstract Assembly { get; } Type type_program = typeof(Program); Console. Write. Line(type_program. Assembly); Type type_al = typeof(Array. List); Console. Write. Line(type_al. Assembly); try { string filename = ". . \Teacher. Library\bin\Debug\Teacher. Library. dll"; Assembly assembly = Assembly. Load. From(filename); Type[] types = assembly. Get. Types(); Console. Write. Line( assembly. Full. Name); foreach (Type curr in types) Console. Write. Line(curr. Name); } catch (Exception ex) { Console. Write. Line(ex. Message); } Вывод : ü В примере выводятся имена сборок, в которых определены классы Program и Array. List, и информация о типах, определенных в сборке Teacher. Library. dll. Reflection_Demo, Version=1. 0. 0. 0, Culture=neutral, Public. Key. Token=null mscorlib, Version=2. 0. 0. 0, Culture=neutral, Public. Key. Token=b 77 a 5 c 561934 e 089 Teacher. Library, Version=1. 0. 0. 0, Culture=neutral, Public. Key. Token=null Teacher Students. List Add. Handler. Args

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

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

Пример определения нового атрибута [Attribute. Usage(Attribute. Targets. Class)] public class My. Comment. Attribute : Пример определения нового атрибута [Attribute. Usage(Attribute. Targets. Class)] public class My. Comment. Attribute : Attribute { string last_update; string comment; public My. Comment. Attribute(string last_update) { this. last_update = last_update; } public string Comment { get { return comment; } set { comment = value; } } }

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

Перечисление Attribute. Targets [Serializable. Attribute] [Flags. Attribute] [Com. Visible. Attribute(true)] public enum Attribute. Targets Перечисление Attribute. Targets [Serializable. Attribute] [Flags. Attribute] [Com. Visible. Attribute(true)] public enum Attribute. Targets ü Перечисление определяет элементы, с которыми можно связать атрибут. ü Элементы перечисления: All Assembly Class Constructor Delegate Enum Event Field Generic. Parameter Interface Method Module Parameter Property Return. Value Struct ü Значения перечисления можно комбинировать с помощью побитовой операци OR.

Использование нового атрибута ü Объявляем класс и указываем атрибут [My. Comment( Использование нового атрибута ü Объявляем класс и указываем атрибут [My. Comment("09. 11. 10", Comment = "Внесены изменения")] [Serializable] class Program{ …} ü Список атрибутов получаем при помощи метода Get. Custom. Attributes() Type type = typeof(Program); object[] attributes = type. Get. Custom. Attributes(true); Console. Write. Line("attributes. Length = " + attributes. Length + "n" + ((My. Comment. Attribute)attributes[0]). Comment + " " + ((My. Comment. Attribute)attributes[0]). Last. Update);

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

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

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

Атрибут Conditional. Attribute - пример ü File Class 1. cs Метод F класса Abc Атрибут Conditional. Attribute - пример ü File Class 1. cs Метод F класса Abc определен с атрибутом Conditional. Символ FAbc не определен. using System; using System. Diagnostics; namespace Conditional_Demo { class Class 1 { static void Main(string[] args) { Abc abc = new Abc(); abc. F(); Console. Write. Line (“ 1”); Class 2 cl 2= new Class 2(); cl 2. F 2(); } } class Abc { [Conditional("FAbc")] public void F() {Console. Write. Line("Abc. F"); } }} ü File Class 2. cs. Символ FAbc определен. #define FAbc using System; namespace Conditional_Demo { public class Class 2 { public void F 2() { Abc abc = new Abc(); abc. F(); } }} ü Вывод: 1 Abc. F