Как вы прокручиваете загруженные в настоящее время сборки?
У меня есть страница «диагностики» в моем приложении ASP.NET, которая делает такие вещи, как проверка соединений с базой данных, отображение текущих настроек приложений и подключений и т. Д. В разделе этой страницы отображаются версии сборок важных типов, используемые в , но я не мог понять, как эффективно показывать версии ВСЕ загруженных сборок.
Каков наиболее эффективный способ определения всех собранных в настоящее время и / или загруженных ассемблий в приложении .NET?
Примечание. Мне не нужны методы на основе файлов, такие как итерация через * .dll в определенном каталоге. Меня интересует, что приложение фактически использует прямо сейчас.
- Самый быстрый способ вычисления 128-битного целого по модулю 64-разрядного целого числа
- x86_64 - Условия сборки и выход из строя
- Сколько циклов процессора требуется для каждой инструкции сборки?
- Не удалось загрузить файл или сборку HRESULT: 0x80131515 (При добавлении controllerа в проект MVC с ссылками на сборку на сетевом диске)
- Сделать муравей тихий без флага -q?
- Как объединить несколько сборок в один?
- Использование разных версий одной и той же сборки в одной папке
- Размер сборки .NET влияет на производительность?
- Почему mulss занимает всего 3 цикла на Хасуэлле, отличном от таблиц инструкций Агнера?
- Что регистрирует сохранение в соглашении вызова ARM C?
- Код C ++ для проверки гипотезы Collatz быстрее, чем assembly вручную - почему?
- Ошибка в построении gradleа после обновления Android Studio с log4j
- Есть ли альтернатива Maven или порт для мира .NET?
Этот метод расширений рекурсивно решает все ссылочные сборки, включая вложенные сборки.
Поскольку он использует ReflectionOnlyLoad
, он загружает сборки в отдельный AppDomain, который имеет то преимущество, что не мешает процессу JIT.
Вы заметите, что есть также MyGetMissingAssembliesRecursive
. Вы можете использовать это для обнаружения любых отсутствующих сборок, на которые ссылаются, но по какой-либо причине не присутствуют в текущем каталоге. Это невероятно полезно при использовании MEF . В возвратном списке вы получите как недостающую сборку, так и ее владельца (ее родителя).
/// /// Intent: Get referenced assemblies, either recursively or flat. Not thread safe, if running in a multi /// threaded environment must use locks. /// public static class GetReferencedAssemblies { static void Demo() { var referencedAssemblies = Assembly.GetEntryAssembly().MyGetReferencedAssembliesRecursive(); var missingAssemblies = Assembly.GetEntryAssembly().MyGetMissingAssembliesRecursive(); // Can use this within a class. //var referencedAssemblies = this.MyGetReferencedAssembliesRecursive(); } public class MissingAssembly { public MissingAssembly(string missingAssemblyName, string missingAssemblyNameParent) { MissingAssemblyName = missingAssemblyName; MissingAssemblyNameParent = missingAssemblyNameParent; } public string MissingAssemblyName { get; set; } public string MissingAssemblyNameParent { get; set; } } private static Dictionary _dependentAssemblyList; private static List _missingAssemblyList; /// /// Intent: Get assemblies referenced by entry assembly. Not recursive. /// public static List MyGetReferencedAssembliesFlat(this Type type) { var results = type.Assembly.GetReferencedAssemblies(); return results.Select(o => o.FullName).OrderBy(o => o).ToList(); } /// /// Intent: Get assemblies currently dependent on entry assembly. Recursive. /// public static Dictionary MyGetReferencedAssembliesRecursive(this Assembly assembly) { _dependentAssemblyList = new Dictionary(); _missingAssemblyList = new List(); InternalGetDependentAssembliesRecursive(assembly); // Only include assemblies that we wrote ourselves (ignore ones from GAC). var keysToRemove = _dependentAssemblyList.Values.Where( o => o.GlobalAssemblyCache == true).ToList(); foreach (var k in keysToRemove) { _dependentAssemblyList.Remove(k.FullName.MyToName()); } return _dependentAssemblyList; } /// /// Intent: Get missing assemblies. /// public static List MyGetMissingAssembliesRecursive(this Assembly assembly) { _dependentAssemblyList = new Dictionary(); _missingAssemblyList = new List (); InternalGetDependentAssembliesRecursive(assembly); return _missingAssemblyList; } /// /// Intent: Internal recursive class to get all dependent assemblies, and all dependent assemblies of /// dependent assemblies, etc. /// private static void InternalGetDependentAssembliesRecursive(Assembly assembly) { // Load assemblies with newest versions first. Omitting the ordering results in false positives on // _missingAssemblyList. var referencedAssemblies = assembly.GetReferencedAssemblies() .OrderByDescending(o => o.Version); foreach (var r in referencedAssemblies) { if (String.IsNullOrEmpty(assembly.FullName)) { continue; } if (_dependentAssemblyList.ContainsKey(r.FullName.MyToName()) == false) { try { var a = Assembly.ReflectionOnlyLoad(r.FullName); _dependentAssemblyList[a.FullName.MyToName()] = a; InternalGetDependentAssembliesRecursive(a); } catch (Exception ex) { _missingAssemblyList.Add(new MissingAssembly(r.FullName.Split(',')[0], assembly.FullName.MyToName())); } } } } private static string MyToName(this string fullName) { return fullName.Split(',')[0]; } }
Обновить
Чтобы сделать этот stream кода безопасным, поместите вокруг него lock
. По умолчанию он не является streamобезопасным, поскольку он ссылается на общую статическую глобальную переменную, чтобы сделать свою магию.
Получение загруженных сборок для текущего AppDomain
:
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
Получение сборок, на которые ссылается другая assembly:
var referencedAssemblies = someAssembly.GetReferencedAssemblies();
Обратите внимание, что если assembly A связывает сборку B и сборку A, это не означает, что assembly B также загружается. Сборка B будет загружаться только тогда, когда это необходимо. По этой причине GetReferencedAssemblies()
возвращает экземпляры AssemblyName
а не экземпляры Assembly
.