ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание
Шрифт:
Кроме того, тип AppDomain определяет небольшой набор событий, соответствующих различным моментам цикла существования домена приложения (табл. 13.5).
Таблица 13.4. Основные члены класса AppDomain
Член | Описание |
---|---|
CreateDomain | Статический метод, с помощью которого создается новый домен приложения в данном процессе. Среда CLR сама создает новые домены приложения по мере необходимости, поэтому вероятность того, что вам понадобится вызывать этот член, близка к нулю |
GetCurrentThreadId | Статический метод, возвращающий ID активного потока в данном домене приложения |
Unload | Еще один статический
|
BaseDirectory | Свойство, возвращающее базовый каталог, используемый при поиске зависимых компоновочных блоков |
CreateInstance | Метод, создающий экземпляр указанного типа, определенного в указанном файле компоновочного блока |
ExecuteAssembly | Метод, выполняющий компоновочный блок в рамках домена приложения, заданного именем файла |
GetAssemblies | Метод, который читает список компоновочных блоков .NET, загруженных в данном домене приложения (двоичные файлы COM и C игнорируются) |
Load | Метод, используемый для динамической загрузки компоновочного блока в рамках данного домена приложения |
Таблица 13.5. События типа AppDomain
Событие | Описание |
---|---|
AssemblyLoad | Возникает при загрузке компоновочного блока |
AssemblyResolve | Возникает, когда не удается идентифицировать компоновочный блок |
DomainUnload | Возникает перед началом выгрузки домена приложения |
ProcessExit | Возникает для домена приложения, созданного по умолчанию, когда завершается родительский процесс этого домена |
ResourceResolve | Возникает, когда не удается идентифицировать ресурс |
TypeResolve | Возникает, когда не удается идентифицировать тип |
UnhandledException | Возникает, когда остается без обработки сгенерированное исключение |
Список доменов приложения процесса
Для примера программного взаимодействия с доменами приложений .NET предположим, что у нас есть новое консольное приложение C# с именем AppDomainManipulator, в рамках которого определяется статический метод PrintAllAssembliesInAppDomain. Этот вспомогательный метод использует AppDomain.GetAssemblies, чтобы получить список всех двоичных файлов .NET, выполняющихся в рамках данного домена приложения.
Соответствующий список представляется массивом типов System.Reflection. Assembly, поэтому необходимо использовать пространство имен System. Reflection (см. главу 12). Получив массив компоновочных блоков, вы выполняете цикл по элементам массива и печатаете понятное имя и версию каждого модуля.
Теперь обновим метод Main, чтобы перед вызовом PrintAllAssembliesInAppDomain получить ссылку на текущий домен приложения, используя свойство AppDomain.CurrentDomain.
Чтобы сделать пример более интересным, метод Main открывает окно сообщения Windows Forms (для этого среда CLR должна загрузить компоновочные блоки System.Windows.Forms.dll, System.Drawing.dll и System.dll, так что не забудьте установить ссылки на эти компоновочные блоки и соответственно изменить набор операторов using).
На рис. 13.6 показан соответствующий вывод (номера версий у вас могут быть другими).
Рис. 13.6. Перечень компоновочных блоков в рамках текущего домена приложений
Программное создание новых доменов приложения
Напомним, что один процесс может содержать множество доменов приложения, И хотя вам в программном коде вряд ли понадобится вручную создавать домены приложения, вы имеете возможность сделать это с помощью статического метода CreateDomain. Нетрудно догадаться, что метод AppDomain.CreateDomain перегружен. Вы, по крайней мере, должны указать понятное имя нового домена приложения, как показано ниже.
Если выполнить приложение теперь (рис. 13.7), вы увидите, что компоновочные блоки System.Windows.Forms.dll, System.Drawing.dll и System.dll будут загружены только в рамках домена приложения, созданного по умолчанию. Это может показаться нелогичным для тех. кто имеете опыт программирования с использованием традиционных подходов Win32 (скорее, оба домена приложения должны иметь доступ к одному и тому же множеству компоновочных блоков). Напомним, однако, о том. что компоновочный блок загружается в рамки домена приложения а не в рамки непосредственно самого процесса.
Рис. 13.7. Один процесс с двумя доменами приложения
Далее, обратите внимание на то, что домен приложения SecondAppDomain автоматически получает свою собственную копию mscorlib.dll, поскольку этот ключевой компоновочный блок автоматически загружается средой CLR для каждого домена приложения. Это порождает следующий вопрос "Как можно программно загрузить компоновочный блок в домен приложения?" Ответ: с помощью метода АррDomain.Load (или, альтернативно, с помощью AppDomain.executeAssembly). В предположении, что вы скопировали CarLibrary.dll в каталог приложения AppDomainManipulator.exe, вы можете загрузить CarLibrary.dll в домен приложения SecondAppDomain так.
Чтобы закрепить понимание взаимосвязей между процессами, доменами приложения и компоновочными блоками, рассмотрите рис. 13.8, на котором представлена диаграмма внутреннего устройства только что построенного процесса AppDomainManipulator.exe.
Рис. 13.8. Схема функционирования процесса AppDomainManipulator.exe
Программная выгрузка доменов приложения
Важно понимать, что среда CLR не позволяет выгружать отдельные компоновочные блоки .NET. Однако, используя метод AppDomain.Unload, вы можете избирательно выгрузить домен приложения из объемлющего процесса. При этом домен приложения выгрузит по очереди каждый компоновочный блок.