Ответ 1
Ниже скопировано из Don Box отличное Essential.Net. (доступно здесь)
(и, imho, должно быть для любого профессионального разработчика .Net)
Загрузчик CLR
Загрузчик CLR отвечает за загрузку и инициализацию сборок, модулей, ресурсов и типов. Загрузчик CLR загружается и инициализируется как можно меньше. В отличие от загрузчика Win32, загрузчик CLR не разрешает и автоматически загружает подчиненные модули (или сборки). Скорее, подчиненные части загружаются по требованию только в том случае, если они действительно необходимы (как в случае с функцией задержки при загрузке Visual С++ 6.0). Это не только ускоряет время инициализации программы, но и уменьшает количество ресурсов, потребляемых запущенной программой. В CLR загрузка обычно запускается компилятором Just-time (JIT) на основе типов. Когда компилятор JIT пытается преобразовать тело метода из CIL в машинный код, ему необходим доступ к типу определения типа объявления, а также определения типов для полей типа. Более того, компилятору JIT также необходим доступ к определениям типов, используемым любыми локальными переменными или параметрами метода, скомпилированным JIT. Загрузка типа подразумевает загрузку как сборки, так и модуля, который содержит определение типа. Эта политика типов загрузки (и сборок и модулей) по требованию означает, что части программы, которые не используются, никогда не попадают в память. Это также означает, что работающее приложение часто увидит новые сборки и модули, загруженные с течением времени, поскольку типы, содержащиеся в этих файлах, необходимы во время выполнения. Если это не то поведение, которое вы хотите, у вас есть два варианта. Один из них - просто объявить скрытые статические поля типов, которые вы хотите явно взаимодействовать с загрузчиком.
Обычно загрузчик выполняет свою работу неявно от вашего имени. Разработчики могут напрямую взаимодействовать с загрузчиком через загрузчик сборок. Сборщик загружается разработчиками с помощью статического метода LoadFrom
в классе System.Reflection.Assembly
. Этот метод принимает строку CODEBASE, которая может быть либо путем файловой системы, либо единым локатором ресурсов (URL), который идентифицирует модуль, содержащий манифест сборки. Если указанный файл не найден, загрузчик будет генерировать исключение System.FileNotFoundException
. Если указанный файл можно найти, но не является модулем CLR, содержащим манифест сборки, загрузчик будет генерировать исключение System.BadImageFormatException
. Наконец, если CODEBASE - это URL-адрес, который использует схему, отличную от file:
, вызывающий должен иметь права доступа WebPermission, иначе генерируется исключение System.SecurityException
. Кроме того, сборка по URL-адресам с протоколами, отличными от file:
, сначала загружается в кэш загрузки до загрузки.
В листинге 2.2 показана простая программа С#, которая загружает сборку, расположенную в file://C:/usr/bin/xyzzy.dll
, а затем создает экземпляр содержащегося типа с именем AcmeCorp.LOB.Customer
. В этом примере все, что предоставляется вызывающим абонентом, является физическим расположением сборки.
Когда программа использует загрузчик сборок таким образом, CLR игнорирует четырехчастное имя сборки, включая номер версии.
Пример 2. 2. Загрузка сборки с явной CODEBASE
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.LoadFrom(
"file: //C:/usr/bin/xyzzy. dll") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}
Хотя загрузка сборок по местоположению несколько интересна, большинство сборок загружаются по имени с помощью преобразователя. Агрегатор сборки использует имя сборки из четырех частей, чтобы определить, какой базовый файл загружается в память, используя загрузчик сборок. Как показано в Рисунок 2.9, этот процесс разрешения имен для местоположения учитывает множество факторов, включая каталог, в котором размещено приложение, политики версий и другие детали конфигурации (все из которых будут рассмотрены далее в этой главе).
Решатель сборки отображается разработчикам с помощью метода Load
класса System.Reflection.Assembly
. Как показано в листинге 2.3, этот метод принимает имя сборки с четырьмя частями (либо как строка, либо как ссылка AssemblyName), и внешне похоже похоже на метод LoadFrom, открытый загрузчиком сборки. Сходство является только глубоким, потому что метод Load сначала использует распознаватель сборки для поиска подходящего файла с использованием довольно сложной серии операций. Первая из этих операций - применить политику версий, чтобы точно определить, какая версия нужной сборки должна быть загружена.
Пример 2.3. Загрузка сборки с помощью резонатора сборки
using System;
using System.Reflection;
public class Utilities {
public static Object LoadCustomerType() {
Assembly a = Assembly.Load(
"xyzzy, Version=1. 2. 3.4, " +
"Culture=neutral, PublicKeyToken=9a33f27632997fcc") ;
return a.CreateInstance("AcmeCorp.LOB.Customer") ;
}
}