Следующая копия с Дон Бокса отлично Essential .Net . (доступно здесь )
(и, imho, должен иметь любой профессиональный разработчик .Net)
Загрузчик CLR
Загрузчик CLR отвечает за загрузку и инициализацию сборок, модулей, ресурсов и типов. Загрузчик CLR загружает и инициализирует настолько мало, насколько это возможно. В отличие от загрузчика Win32, загрузчик CLR не разрешает и автоматически загружает подчиненные модули (или сборки).
Скорее, подчиненные части загружаются по требованию, только если они действительно необходимы (как с функцией отложенной загрузки Visual C ++ 6.0). Это не только ускоряет время инициализации программы, но и уменьшает количество ресурсов, потребляемых работающей программой.
В CLR загрузка обычно запускается компилятором JIT (Just in Time), основанным на типах. Когда 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 показана простая программа на C #, которая загружает сборку, расположенную в 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. Загрузка сборки с помощью Resolver Assembly
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") ;
}
}