Как вы прокручиваете загруженные в настоящее время сборки?

У меня есть страница «диагностики» в моем приложении ASP.NET, которая делает такие вещи, как проверка соединений с базой данных, отображение текущих настроек приложений и подключений и т. Д. В разделе этой страницы отображаются версии сборок важных типов, используемые в , но я не мог понять, как эффективно показывать версии ВСЕ загруженных сборок.

Каков наиболее эффективный способ определения всех собранных в настоящее время и / или загруженных ассемблий в приложении .NET?

Примечание. Мне не нужны методы на основе файлов, такие как итерация через * .dll в определенном каталоге. Меня интересует, что приложение фактически использует прямо сейчас.

Этот метод расширений рекурсивно решает все ссылочные сборки, включая вложенные сборки.

Поскольку он использует 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 .

  • Цикл с вызовом функции быстрее, чем пустой цикл
  • Поиск всех пространств имен в сборке с использованием Reflection (DotNET)
  • Безопасно ли читать конец конца буфера на одной странице на x86 и x64?
  • Инициализировать библиотеку при загрузке сборки
  • Как ссылаться на сборки .NET с помощью PowerShell
  • Как я могу просмотреть MSIL / CIL, сгенерированный компилятором C #? Почему это называется сборкой?
  • Почему медленная инструкция цикла? Не удалось ли Intel эффективно внедрить его?
  • Эффективное умножение матрицы 4x4 (C vs assembly)
  • Очень быстро memcpy для обработки изображений?
  • Загрузка нескольких версий одной и той же сборки
  • Правильное изменение неопределенного поведения, если число больше ширины типа?
  • Interesting Posts
    Давайте будем гением компьютера.