- •Введение Обзор .Net. Основные понятия
- •Программа на c#
- •Основы языка Пространство имён
- •Система типов
- •Класс и Структура. Первое приближение
- •Литералы. Представление значений
- •Арифметические литералы
- •Логические литералы
- •Символьные литералы
- •Символьные escape-последовательности
- •Строковые литералы
- •Операции и выражения
- •Приоритет операций
- •Приведение типов
- •Особенности выполнения арифметических операций
- •Особенности арифметики с плавающей точкой
- •Константное выражение
- •Переменные элементарных типов. Объявление и инициализация
- •Константы
- •Перечисления
- •Объявление переменных. Область видимости и время жизни
- •Управляющие операторы
- •Синтаксис объявления метода
- •Вызов метода
- •Перегрузка методов
- •Способы передачи параметров при вызове метода
- •Передача параметров. Ссылка и ссылка на ссылку как параметры
- •Сравнение значений ссылок
- •This в нестатическом методе
- •Свойства
- •Обработка исключений
- •Массив. Объявление
- •Инициализация массивов
- •Примеры инициализации массивов
- •Два типа массивов: Value Type and Reference Type
- •Встроенный сервис по обслуживанию простых массивов
- •Реализация сортировки в массиве стандартными методами
- •Подробнее о массивах массивов (jagged array)
- •Массивы как параметры
- •Спецификатор params
- •Main в классе. Точка входа
- •Создание объекта. Конструктор
- •Операция new
- •В управляемой памяти нет ничего, что бы создавалось без конструктора
- •Кто строит конструктор умолчания
- •This в контексте конструктора
- •Перегрузка операций
- •Синтаксис объявления операторной функции
- •Унарные операции. Пример объявления и вызова
- •Бинарные операции
- •Определение операций конъюнкция и дизъюнкции
- •И вот результат…
- •Пример. Свойства и индексаторы
- •Explicit и implicit. Преобразования явные и неявные
- •Наследование
- •Наследование и проблемы доступа
- •Явное обращение к конструктору базового класса
- •Кто строит базовый элемент
- •Переопределение членов базового класса
- •Наследование и new модификатор
- •Полное квалифицированное имя. Примеры использования
- •Прекращение наследования. Sealed спецификатор
- •Абстрактные функции и абстрактные классы
- •Ссылка на объект базового класса
- •Операции is и as
- •Виртуальные функции. Принцип полиморфизма
- •Интерфейсы
- •Делегаты
- •События
- •События и делегаты. Различия
- •Атрибуты, сборки, рефлексия Рефлексия (отражение) типов
- •Реализация отражения. Type, InvokeMember, BindingFlags
- •Атрибуты
- •Сборка. Класс Assembly
- •Класс сборки в действии
- •Разбор полётов
- •Класс System.Activator
- •Версия сборки
- •Файл конфигурации приложения
- •Общедоступная сборка
- •Игры со сборками из gac
- •Динамические сборки
- •Динамическая сборка: создание, сохранение, загрузка, выполнение
- •Ввод-вывод Базовые операции
- •Потоки: байтовые, символьные, двоичные
- •Предопределённые потоки ввода-вывода
- •Функция ToString()
- •Консольный ввод-вывод. Функции-члены класса Console
- •Консольный вывод. Форматирование
- •Функции вывода. Нестандартное (custom) форматирование значений.
- •Консольный ввод. Преобразование значений
- •Файловый ввод-вывод
- •Потоки Процесс, поток, домен
- •Домен приложения
- •Обзор пространства имён System.Threading
- •Многопоточность
- •Виды многопоточности
- •А кто в домене живёт…
- •Класс Thread. Общая характеристика
- •Именование потока
- •Игры с потоками
- •Характеристики точки входа дополнительного потока
- •Запуск вторичных потоков
- •Приостановка выполнения потока
- •Отстранение потока от выполнения
- •Завершение потоков
- •Метод Join()
- •Состояния потока (перечисление ThreadState)
- •Одновременное пребывание потока в различных состояниях
- •Фоновый поток
- •Приоритет потока
- •Передача данных во вторичный поток
- •Извлечение значений (данных) с помощью Callback методов
- •Организация взаимодействия потоков
- •1. Посредством общедоступных (public) данных
- •2. Посредством общедоступных (public) свойств
- •3. Посредством общедоступных очередей
- •Состязание потоков
- •Блокировки и тупики
- •Очереди. Основа интерфейса взаимодействия
- •Безопасность данных и критические секции кода
- •Пример организации многопоточного приложения
- •Очередь как объект синхронизации
- •Синхронизация работы потоков при работе с общими ресурсами
- •1. Организация критических секций
- •2. Специальные возможности мониторов
- •Рекомендации по недопущению блокировок потоков
- •Форма Класс Form
- •Форма: управление и события жизненного цикла
- •Форма: контейнер как элемент управления
- •Разница между элементами управления и компонентами.
- •Свойства элементов управления. Anchor и Dock
- •Extender providers. Провайдеры дополнительных свойств
- •Validating и Validated элементов управления
- •Управление посредством сообщений
- •Стандартный делегат
- •Делегат EventHandler
- •Класс Application
- •События класса Application
- •Примеры перехвата сообщений
- •Метод WndProc
- •Пример переопределения WndProc
- •Контекст приложения
- •Применение классов GraphicsPath и Region. Круглая форма
- •Собственные элементы управления
- •Литература
Класс сборки в действии
Исследование свойств и областей применения класса Assembly начинаем с создания тестовой однофайловой сборки AssemblyForStart в рамках проекта Class Library.
Первая сборка Operators00.exe:
using System;
namespace Operators00
{
public class xPoint
{
float x, y;
xPoint()
{
x = 0.0F;
y = 0.0F;
}
public xPoint(float xKey, float yKey):this()
{
x = xKey;
y = yKey;
}
public static bool operator true(xPoint xp)
{
if (xp.x != 0.0F && xp.y != 0.0F) return true;
else return false;
}
public static bool operator false(xPoint xp)
{
if (xp.x == 0.0F || xp.y == 0.0F) return false;
else return true;
}
public static xPoint operator | (xPoint key1, xPoint key2)
{
if (key1) return key1;
if (key2) return key2;
return new xPoint();
}
public static xPoint operator & (xPoint key1, xPoint key2)
{
if (key1 && key2) return new xPoint(1.0F, 1.0F);
return new xPoint();
}
public void Hello()
{
Console.WriteLine(“Hello! Point {0},{1} is here!”,this.x,this.y);
}
}
class Class1
{
/// <summary>
/// The main entry Point for the application.
/// </summary>
[STAThread]
static void Main() // У точки входа пустой список параметров.
// Я пока не сумел ей передать через метод Invoke массива строк.
{
xPoint xp0 = new xPoint(1.0F, 1.0F);
xPoint xp1 = new xPoint(1.0F, 1.0F);
if (xp0 || xp1) Console.WriteLine(“xp0 || xp1 is true!”);
else Console.WriteLine(“xp0 || xp1 is false!”);
}
}
}
Вторая сборка AssemblyForStart.dll. В примере она так и не запускалась. Используется только для тестирования стандартных средств загрузки сборок-библиотек классов.
using System;
namespace AssemblyForStart
{
/// <summary>
/// Class1 : первая компонента сборки AssemblyForStart.
/// </summary>
public class Class1
{
public Class1()
{
Console.WriteLine(“This is constructor Class1()”);
}
public void fC1()
{
Console.WriteLine(“This is fC1()”);
}
}
}
А вот полигон AssemblyStarter.exe. В примере демонстрируется техника ПОЗДНЕГО СВЯЗЫВАНИЯ. Именно поэтому код, который выполняется после загрузки сборки не содержит в явном виде информации об используемых в приложении типах. Транслятор действует в строгом соответствии с синтаксисом языка C# и просто не поймёт пожелания “создать объект-представитель класса … который будет объявлен в сборке, которую предполагается загрузить в ходе выполнения приложения”.
using System;
using System.Reflection;
using System.IO;
namespace AssemblyStarter
{
/// <summary>
/// Приложение обеспечивает запуск сборки.
/// </summary>
class Class1
{
static void Main(string[] args)
{
// Сборка может быть вызвана непосредственно по имени
// (строковый литерал с дружественным именем сборки).
// Ничего особенного. Просто имя без всяких там расширений.
// Главная проблема заключается в том, сборки должны предварительно
// включаться в раздел References (Ссылки).
// Кроме того, информация о загружаемой сборке может быть представлена
// в виде объекта - представителя класса AssemblyName, ссылка на который
// также может быть передана в качестве аргумента методу Assembly.Load().
// Вот здесь как раз и происходит формирование этого самого объекта.
AssemblyName asmName = new AssemblyName();
asmName.Name = “AssemblyForStart”;
// Версию подсмотрели в манифесте сборки с помощью IlDasm.exe.
Version v = new Version(“1.0.1790.25124”);
// Можно было бы для пущей крутизны кода поле Version проинициализировать
// непосредственно (дело хозяйское):
// asmName.Version = new Version(«1:0:1790:25124»);
asmName.Version = v;
// Ссылка на объект-представитель класса Assembly.
//
Assembly asm = null;
try
{
// Загрузка сборки по «дружественному имени».
//asm = Assembly.Load(«AssemblyForStart»);
// Путь и полное имя при загрузки частной сборки не имеют значения.
// Соответствующие файлы должны располагаться непосредственно в каталоге приложения.
//asm = Assembly.Load
//(@”D:\Users\WORK\Cs\AssemblyTest\AssemblyForStart\bin\Debug\AssemblyForStart.dll”);
//asm = Assembly.Load(asmName);
// Если сборку организовать в виде исполняемого модуля и «запихнуть» в каталог
// вручную - загрузится и такая сборка.
asm = Assembly.Load(“Operators00”);
}
catch(FileNotFoundException e)
{
Console.WriteLine(“We have a problem:” + e.Message);
}
// Итак, решено. Загрузили сборку, содержащую объявление класса xPoint.
// Если сборка загрузилась - с ней надо что-то делать. Ясное дело,
// надо выполнять программный код сборки.
// Первый вариант выполнения. В сборке содержатся объявления двух классов:
// класса xPoint и класса Class1. Мы воспользуемся объявлением класса xPoint,
// построим соответствующий объект-представитель этого класса, после чего
// будем вызывать нестатические методы-члены этого класса.
// Всё происходит в режиме ПОЗДНЕГО связывания. Поэтому ни о каких ЯВНЫХ упоминаниях
// имён типов не может быть речи. Единственное явное упоминание - это упоминание
// имени метода.
object[] ps = {25,25};
Type[] types = asm.GetTypes();
// Здесь используется класс Activator!
object obj = Activator.CreateInstance(types[0],ps);
MethodInfo mi = types[0].GetMethod(“Hello”);
mi.Invoke(obj,null);
// Второй вариант выполнения. Воспользуемся тем обстоятельством, что загружаемая
// сборка не является библиотекой классов, а является обычной выполнимой сборкой
// с явным образом обозначенной точкой входа - СТАТИЧЕСКОЙ функцией Main(), которая
// является членом класса Class1.
mi = asm.EntryPoint;
// Вот всё получилось! Единственное, что я не сделал, так это не смог передать
// в точку входа загруженной сборки массива строк-параметров
// (смотреть на точку входа данной сборки).
// Ну не удалось. Потому и в сборке Operators точку сборки объявил без параметров.
mi.Invoke(null,null);
}
}
}
Собрали, запустили. Получилось. Стало быть, ВСЁ ХОРОШО.
В ходе выполнения приложения класс Assembly позволяет:
получать информацию о самой сборке,
обращаться к членам класса, входящим в сборку,
загружать другие сборки.