- •А.А. Волосевич
- •2. Базовые технологии платформы .Net 5
- •2. Базовые технологии платформы .Net 4
- •2. Базовые технологии платформы .Net
- •2.1. Работа с Числами
- •2.2. Дата и время
- •2.3. Работа со строками и текстом
- •2.4. Преобразование информации
- •2.5. Отношения равенства и порядка
- •Сравнение для выяснения равенства
- •Сравнение для выяснения порядка
- •2.6. Жизненный цикл объектов
- •Алгоритм «сборки мусора»
- •Финализаторы и интерфейс iDisposable
- •2.7. Перечислители и итераторы
- •2.8. Интерфейсы стандартных коллекций
- •2.9. Массивы и класс system.Array
- •2.10. Типы для работы с коллекциями-списками
- •2.11. Типы для работы с коллекциями-множествами
- •2.12. Типы для работы с коллекциями-словарями
- •2.13. Типы для создания пользовательских коллекций
- •2.14. Технология linq to objects
- •1. Оператор условия Where().
- •2. Операторы проекций.
- •3. Операторы упорядочивания.
- •4. Оператор группировки GroupBy().
- •5. Операторы соединения.
- •6. Операторы работы с множествами.
- •7. Операторы агрегирования.
- •8. Операторы генерирования.
- •9. Операторы кванторов и сравнения.
- •10. Операторы разбиения.
- •11. Операторы элемента.
- •12. Операторы преобразования.
- •2.15. Работа с объектами файЛовой системы
- •2.16. Ввод и вывод информации
- •Потоки данных и декораторы потоков
- •2. Классы для работы с потоками, связанными с хранилищами.
- •3. Декораторы потоков.
- •4. Адаптеры потоков.
- •Адаптеры потоков
- •2.17. Основы xml
- •2.18. Технология linq to xml
- •Создание, сохранение, загрузка xml
- •Запросы, модификация и трансформация xml
- •Пространства имен xml
- •2.19. ДОполнительные возможности обработки xml
- •2.20. Сериализация
- •Сериализация времени выполнения
- •Сериализация контрактов данных
- •2.21. Состав и взаимодействие сборок
- •2.22. Метаданные и получение информации о типах
- •2.23. Позднее связывание и кодогенерация
- •2.24. Динамические типы
- •2.25. Атрибуты
- •2.26. Файлы конфигуРации
- •2.27. Основы мНогопоточноГо программирования
- •2.28. Синхронизация потоков
- •2.29. Библиотека параллельных расширений
- •Параллелизм на уровне задач
- •Параллелизм при императивной обработке данных
- •Параллелизм при декларативной обработке данных
- •Обработка исключений и отмена выполнения задач
- •Коллекции, поддерживающие параллелизм
- •2.30. Асинхронный вызов методов
- •2.31. Процессы и домены
- •2.32. Безопасность
- •Разрешения на доступ
- •Изолированные хранилища
- •Криптография
- •2.33. Диагностика
2.24. Динамические типы
Динамические типы – новый элемент языка C# и платформы .NET четвёртой версии. При использовании динамического типа компилятор не выполняет у объекта проверку элементов типа. Такая проверка происходит при выполнении кода, после связывания динамической переменной с конкретным объектом.
Мотивом введения динамических типов была необходимость упростить работу C#-кода с COM-объектами и сценарными языками. Ниже приведён листинг, в котором выполняется взаимодействие с Microsoft Excel.
// получаем тип, соответствующий объекту Microsoft Excel
Type xlAppType = Type.GetTypeFromProgID("Excel.Application");
// объявляем переменную, используя динамический тип
dynamic xl = Activator.CreateInstance(xlAppType);
// вызываем некоторые методы Excel
xl.Visible = true; // показываем окно Excel
dynamic workbooks = xl.Workbooks; // создаем новый лист Excel
workbooks.Add(-4167);
xl.Cells[1, 1].Value2 = "C# Rocks!"; // заполняем ячейку листа
Пример показывает, что объект динамического типа объявляется при помощи ключевого слова dynamic. У такого объекта можно записать вызов любого метода или свойства, это не влияет на компиляцию. С точки зрения компилятора dynamic является эквивалентом object. Задача компилятора – «упаковать» информацию о действиях, производимых с динамическим объектом, чтобы среда исполнения могла правильно таким объектом распорядиться.
// объявляем простой класс
public class Foo
{
public void Do(string s) { Console.WriteLine(s); }
}
// код компилируется (!),
// но при выполнении 3-я строка генерирует исключение
dynamic obj = new Foo();
obj.Do("Hello");
obj.Prop = 3; // исключение!
Действия среды исполнения зависят от вида объекта, связываемого с динамической переменной:
-
Обычные объекты .NET – элементы типа определяются при помощи механизма отражения, работа с элементами происходит при помощи позднего связывания.
-
Объект, реализующий интерфейс IDynamicMetaObjectProvider – сам объект запрашивается о том, содержит ли он заданный элемент. В случае успеха работа с элементом делегируется объекту.
-
COM-объекты – работа с элементами происходит через интерфейс IDispatch.
Интерфейс IDynamicMetaObjectProvider позволяет разработчикам создавать типы, обладающие динамическим поведением. Обычно данный интерфейс не реализуется напрямую, а выполняется наследование от класса DynamicObject (интерфейс и класс находятся в пространстве имён System.Dynamic). Ниже приведён пример класса, унаследованного от DynamicObject.
public class MyDynamicType : DynamicObject
{
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args, out object result)
{
Console.WriteLine("Вызов {0}.{1}()",
GetType(), binder.Name);
result = null;
return true;
}
public override bool TrySetMember(SetMemberBinder binder,
object value)
{
Console.WriteLine("Установка {0}.{1} в значение {2}",
GetType(), binder.Name, value);
return true;
}
public void DoDefaultWork()
{
Console.WriteLine("Некое действие");
}
}
// пример использования
dynamic d = new MyDynamicType();
d.DoDefaultWork(); // "Некое действие"
d.DoWork(); // "Вызов MyDynamicType.DoWork()"
d.Value = 42; // "Установка MyDynamicType.Value в значение 42"
d.Count = 12; // "Установка MyDynamicType.Count в значение 12"
Класс System.Dynamic.ExpandoObject позволяет при выполнении программы добавлять и удалять элементы своего экземпляра:
public sealed class ExpandoObject : IDynamicMetaObjectProvider,
IDictionary<string, object>,
INotifyPropertyChanged
Благодаря динамическому типизированию, работа с пользовательскими элементами ExpandoObject происходит как работа с обычными элементами объекта. Ниже приведён пример расширения ExpandoObject двумя свойствами и методом (в виде делегата).
dynamic sample = new ExpandoObject();
sample.Caption = "Свойство"; // добавляем свойство Caption
sample.Number = 10; // и числовое свойство Number
sample.Increment = (Action)(() => { sample.Number++; });
// работаем с объектом sample
Console.WriteLine(sample.Caption); // Свойство
Console.WriteLine(sample.Caption.GetType()); // System.String
sample.Increment();
Console.WriteLine(sample.Number); // 11
Объект ExpandoObject явно реализует IDictionary<string, object>. Это позволяет инспектировать элементы объекта при выполнении программы. Также при помощи словаря удаляются элементы объекта ExpandoObject.
dynamic employee = new ExpandoObject();
employee.Name = "John Smith";
employee.Age = 33;
foreach (var property in (IDictionary<string, object>)employee)
{
Console.WriteLine(property.Key + ": " + property.Value);
}
((IDictionary<string, object>)employee).Remove("Name");
Реализация в ExpandoObject интерфейса INotifyPropertyChanged позволяет получать уведомления при изменении свойств объекта ExpandoObject.