Именно JIT-компилятор управляет загрузкой сборок в ответ на перевод IL в машинный код. Вызовы методов типа сначала переводятся для вызова функции-заглушки. При вызове эта заглушка активирует JIT-компилятор, чтобы загрузить IL (который загружает сборку при необходимости) и преобразовать его. Очень по запросу.
Одним из препятствий в этом процессе являются сборки, которые запускались через Ngen.exe, все сборки платформы .NET были, когда они были установлены на компьютере. Это обнаруживается при первой загрузке сборки. Затем JIT-компилятор пропускает этап перевода и использует предварительно переведенный машинный код как есть. Хотя при этом будет загружен весь машинный код, созданный сборкой, он все еще по требованию. Термин «загрузка» здесь относителен, Windows использует файл отображения памяти для сопоставления собственного образа с пространством виртуальной памяти. Фактические байты не считываются из файла до тех пор, пока выполнение кода не попадет на страницу памяти, которая еще не была отображена в ОЗУ. Технический термин для этого - «ошибка страницы», он виден в Taskmgr.exe.