
- •1. Язык программирования c# 3
- •2. Базовые элементы .Net Framework 67
- •3. ТЕхнология .Net Remoting 144
- •Введение
- •1. Язык программирования c#
- •1.1. Платформа .Net – обзор архитектуры
- •1.2. Язык c# - общие концепции синтаксиса
- •1.3. Система типов языка c#
- •1.4. Преобразования типов
- •1.5. Идентификаторы, ключевые слова и литералы
- •1.6. Объявление переменных, полей и констант
- •1.7. Выражения и операции
- •1.8. Операторы языка c#
- •1.9. Объявление и вызов методов
- •1.10. Массивы в c#
- •1.11. Работа с символами и строками в c#
- •1.12. Синтаксис объявления класса, Поля и методы класса
- •1.13. Свойства и индексаторы
- •1.14. Конструкторы класса и Жизненный цикл объекта
- •1.15. Наследование классов
- •1.16. Перегрузка операЦий
- •1.17. Делегаты
- •1.18. События
- •1.19. Интерфейсы
- •1.20. Структуры и перечисления
- •1.21. Пространства имен
- •1.22. Генерация и обработка исключительных ситуаций
- •1.23. Нововведения в языке c# 2.0
- •1.24. Обобщенные типы (generics)
- •2. Базовые элементы .Net Framework
- •2.1. Метаданные и механизм отражения
- •2.2. Пользовательские и встроенные атрибуты
- •2.3. Пространство имен system.Collections
- •2.4. Работа с файлами и директориями
- •2.5. Использование потоков данных
- •2.6. Сериализация
- •2.7. Сериализация объектов в нестандартном формате
- •2.8. Введение в xml
- •2.9. Работа с xml-документами в .Net framework
- •2.10. МНогопоточное программирование
- •2.11. Синхронизация потоков
- •2.12. Асинхронный вызов методов
- •2.13. Состав и взаимодействие сборок
- •2.14. Конфигурирование сборок
- •3. ТЕхнология .Net Remoting
- •3.1. Домены приложений
- •3.2. Архитектура .Net Remoting
- •3.3. Активация удаленных объектов и их время жизни
- •3.4. Программная настройка Remoting
- •3.5. Удаленные Объекты с клиентской активацией
- •3.6. Настройка Remoting при помощи конфигурационных файлов
- •3.7. Хостинг распределенных приложений
- •3.8. Объекты-сообщения
- •3.9. Пользовательские канальные приемники
- •4.1. Архитектура ado.Net
- •4.2. Учебная база cd Rent
- •4.3. Соединение с базой данных
- •4.4. Выполнение команд и запросов к базе данных
- •4.5. Чтение данных и объект DataReader
- •4.6. Параметризированные запросы
- •4.7. Рассоединенный набор данных
- •4.8. Заполнение Рассоединенного набора данных
- •4.9. Объект класса DataColumn – колонка таблицы
- •4.10. Объекты класса DataRow – строки таблицы
- •4.11. Работа с объектом класса DataTable
- •4.12. DataSet и схема рассоединенного набора данных
- •4.13. Типизированные DataSet
- •4.14. Поиск и фильтрация данных в DataSet
- •4.15. Класс DataView
- •4.16. СиНхронизация набора данных и базы
- •5.1. Архитектура и общие концепции asp.Net
- •5.2. Пример aspx-страницы. Структура страницы
- •5.3. Директивы страницы
- •5.4. Класс System.Web.Ui.Page. События страницы
- •5.5. Серверные элементы управления
- •5.6. Элементы управления Web Controls
- •5.7. Проверочные элементы управления
- •5.8. Списковые элементы управления
- •5.9. Связывание данных
- •5.11. Управление состояниями в web-приложениях
- •5.12. Кэширование
- •5.13. Безопасность в web-приложениях
- •5.14. Создание пользовательских элементов управления
- •Литература
2. Базовые элементы .Net Framework
2.1. Метаданные и механизм отражения
При программировании для платформы .NET в любую сборку помещаются метаданные, которые являются описанием всех типов данных сборки и их членов. Работа с метаданными происходит при помощи специального механизма, называемого механизмом отражения (reflection).
Главные элементы, которые необходимы для использования возможностей отражения – это класс System.Type и типы из пространства имен System.Reflection.
Класс System.Type служит для получения информации о типе. Для того чтобы получить объект данного класса, существует несколько возможностей.
1. Вызвать у объекта метод GetType(). Данный метод определен на уровне System.Object, а значит присутствует у любого объекта:
Foo A = new Foo(); //Foo – это некий класс
Type t = A.GetType();
2. Использовать статический метод Type.GetType(), которому передается текстовое имя интересующего нас типа:
Type t;
t = Type.GetType("Foo");
3. Использовать ключевое слово языка C# typeof:
Type t = typeof(Foo);
Чтобы продемонстрировать возможности класса Type, опишем вспомогательный класс Foo.
public class Foo {
private int Field1;
public float Field2;
private int Method1() {
Console.WriteLine("Method1 is called");
return 0;
}
public void Method2(string s, ref int i) {
Console.WriteLine("Method2 is called");
Console.WriteLine("First parameter is " + s);
Console.WriteLine("Second parameter is " + i);
}
public int Prop {
get { return Field1; }
set { Field1 = value; }
}
}
А теперь рассмотрим код, который выводит информацию об элементах типа Foo (для использования типов, подобных FieldInfo, необходимо подключить пространство имен System.Reflection).
Type t = typeof(Foo);
//Это общая информация
Console.WriteLine("Full name = " + t.FullName);
Console.WriteLine("Base is = " + t.BaseType);
Console.WriteLine("Is abstract = " + t.IsAbstract);
Console.WriteLine("Is sealed = " + t.IsSealed);
Console.WriteLine("Is class = " + t.IsClass);
Console.WriteLine("******************************");
//Сейчас пройдемся по полям
FieldInfo[] fi = t.GetFields();
foreach(FieldInfo f in fi)
Console.WriteLine("Field = " + f.Name);
Console.WriteLine("******************************");
//А теперь по свойствам
PropertyInfo[] pi = t.GetProperties();
foreach(PropertyInfo p in pi)
Console.WriteLine("Property = " + p.Name);
Console.WriteLine("******************************");
//С методами поработаем подробнее
MethodInfo[] mi = t.GetMethods();
foreach(MethodInfo m in mi) {
Console.WriteLine("Method Name = " + m.Name);
Console.WriteLine("Method Return Type = " + m.ReturnType);
//Изучим параметры метода
ParameterInfo[] pri = m.GetParameters();
foreach(ParameterInfo pr in pri) {
Console.WriteLine("Parameter Name = " + pr.Name);
Console.WriteLine("Type = " + pr.ParameterType);
}
Console.WriteLine("******************************");
}
Данный код выводит следующую информацию:
Full name = refl.Foo
Base is = System.Object
Is abstract = False
Is sealed = False
Is class = True
******************************
Field = Field2
******************************
Property = Prop
******************************
Method Name = GetHashCode
Method Return Type = System.Int32
******************************
Method Name = Equals
Method Return Type = System.Boolean
Parameter Name = obj
Parameter Type = System.Object
******************************
Method Name = ToString
Method Return Type = System.String
******************************
Method Name = Method2
Method Return Type = System.Void
Parameter Name = s
Parameter Type = System.String
Parameter Name = i
Parameter Type = System.Int32&
******************************
Method Name = get_Prop
Method Return Type = System.Int32
******************************
Method Name = set_Prop
Method Return Type = System.Void
Parameter Name = value
Parameter Type = System.Int32
******************************
Method Name = GetType
Method Return Type = System.Type
******************************
Обратите внимание, что была получена информация только об открытых членах класса Foo. Кроме этого, информация включала описание собственных и унаследованных элементов класса Foo. Пространство имен System.Reflection содержит специальное перечисление BindingFlags, которое позволяет управлять получаемой о типе информацией.
Таблица 7
Элементы перечисления BindingFlags
Элемент BindingFlags |
Описание |
Default |
Поиск по умолчанию |
IgnoreCase |
Поиск, не чувствительный к регистру |
DeclaredOnly |
Игнорировать унаследованные члены |
Instance |
Поиск экземплярных членов |
Static |
Поиск статических членов |
Public |
Поиск открытых членов |
NonPublic |
Поиск внутренних членов |
FlattenHierarchy |
Поиск статических членов, заданных в базовых типах |
Методы класса Type, подобные GetFields(), имеют перегруженные версии, в которых одним из параметров выступает набор флагов BindingFlags. Изменим приведенный выше код, чтобы получать информацию об открытых и внутренних методах, определенных в самом классе Foo:
BindingFlags bf = BindingFlags.DeclaredOnly |
BindingFlags.Public | BindingFlags.NonPublic |
BindingFlags.Static | BindingFlags.Instance;
MethodInfo[] mi = t.GetMethods(bf);
// Далее по тексту примера...
Некоторые типы пространства System.Reflection, которые могут быть полезны при работе с метаданными, перечисдены в таблице 8.
Таблица 8
Избранные типы пространства имен System.Reflection
Тип |
Назначение |
Assembly |
Класс для загрузки сборки, изучения ее состава и выполнения операций со сборкой |
AssemblyName |
Класс для получения идентификационной информации о сборке |
EventInfo |
Хранит информацию о событии |
FieldInfo |
Хранит информацию о поле |
MemberInfo |
Абстрактный класс для классов вида *Info |
MethodInfo |
Хранит информацию о методе |
Module |
Позволяет обратиться к модулю в многофайловой сборке |
ParameterInfo |
Хранит информацию о параметре метода |
PropertyInfo |
Хранит информацию о свойстве |
При помощи класса Assembly можно получить информацию обо всех модулях сборки, затем при помощи класса Module получить информацию обо всех типах модуля, далее вывести информацию для отдельного типа. Кроме этого, метод Assembly.Load() позволят динамически загрузить определенную сборку в память во время работы приложения. Подобный подход называется поздним связыванием.
Для демонстрации позднего связывания поместим класс Foo в динамическую библиотеку с именем FooLib.dll. Основное приложение будет загружать данную библиотеку и исследовать ее типы:
using System;
using System.Reflection;
using System.IO; //Нужно для FileNotFoundException
class MainClass {
public static void Main() {
Assembly A = null;
try {
//Используется текстовое имя без расширения
//Файл FooLib.dll находится в директории программы
A = Assembly.Load("FooLib");
} catch (FileNotFoundException e) {
Console.WriteLine(e.Message);
return;
}
foreach(Module M in A.GetModules())
foreach(Type T in M.GetTypes())
// Выводить особо нечего – одна строке Foo
Console.WriteLine(T.Name);
}
}
Позднее связывание не ограничивается загрузкой сборки и изучением состава ее элементов. При помощи позднего связывания можно создать объекты типов, определенных в сборке, а также работать с элементами созданных объектов (например, вызывать методы). Для создания определенного объекта используется метод CreateInstance() класса System.Activator. Существует несколько перегруженных версий данного метода. Можно использовать вариант, при котором в качестве параметра метода используется объект Type или строка-имя типа. Метод возвращает значение типа object. Класс MethodInfo имеет метод Invoke(), который позволяет вызвать метод объекта. Первый параметр метода Invoke() – это тот объект, у которого вызывается метод, второй параметр – массив объектов, представляющих параметры метода.
Представим листинг приложения, которое пытается интерактивно создавать объекты определенных типов и вызывать их методы (для простоты полностью отсутствует обработка исключительных ситуаций):
using System;
using System.Reflection;
using System.IO;
class MainClass {
public static void Main() {
//Просим пользователя ввести имя сборки и считываем ее
Console.Write("Enter the name of assembly: ");
string AssemblyName = Console.ReadLine();
Assembly A = Assembly.Load(AssemblyName);
//Перечисляем все типы в сборке
//(вернее, проходим по модулям сборки и ищем типы в них)
Console.WriteLine("Assembly {0} has types:", AssemblyName);
foreach(Module M in A.GetModules())
foreach(Type T in M.GetTypes())
Console.WriteLine(T.Name);
//Просим пользователя ввести имя типа
Console.Write("Enter namespace.typename: ");
string TypeName = Console.ReadLine();
//Запрашиваем указанный тип и создаем его экземпляр
Type UserType = A.GetType(TypeName);
object obj = Activator.CreateInstance(UserType);
//Перечисляем методы типа (с применением BindingFlags)
Console.WriteLine("Type {0} has methods:", TypeName);
BindingFlags bf = BindingFlags.DeclaredOnly |
BindingFlags.Public |
BindingFlags.NonPublic |
BindingFlags.Static |
BindingFlags.Instance;
foreach(MethodInfo m in UserType.GetMethods(bf))
Console.WriteLine("Method Name = " + m.Name);
//Просим пользователя ввести имя метода
Console.Write("Enter the name of method to call: ");
string MethodName = Console.ReadLine();
//Запрашиваем метод и выводим список его параметров
MethodInfo Method = UserType.GetMethod(MethodName);
Console.WriteLine("Method {0} has parameters:",
MethodName);
foreach(ParameterInfo pr in Method.GetParameters()) {
Console.WriteLine("Parameter Name = " + pr.Name);
Console.WriteLine("Parameter Type = " +
pr.ParameterType);
Console.WriteLine("****************************");
}
// Создаем пустой массив для фактических параметров
object[] paramArray =
new object[Method.GetParameters().Length];
//Вызываем метод
Method.Invoke(obj, paramArray);
}
}