Как вы проходите через загруженные сборки?
У меня есть страница "диагностика" в моем ASP.NET приложение, которое делает такие вещи, как проверка соединения(ов) с базой данных, отображение текущих appSettings и ConnectionStrings и т. д. В разделе этой страницы отображаются версии сборок важных типов, используемых повсюду, но я не мог понять, как эффективно отображать версии всех загруженных сборок.
какой самый эффективный способ выяснить все в настоящее время ссылки и / или загружены Сборки в приложении .NET?
Примечание: меня не интересуют методы на основе файлов, такие как итерация через *.dll в определенном каталоге. Я заинтересован в том, что приложение на самом деле используя прямо сейчас.
2 ответов:
этот метод расширения возвращает все ссылочные сборки, рекурсивно, включая вложенные сборки.
как он использует
ReflectionOnlyLoad, он загружает сборки в отдельном домене приложения, что имеет то преимущество, что не вмешивается в процесс JIT.вы заметите, что есть также
MyGetMissingAssembliesRecursive. Это можно использовать для обнаружения отсутствующих сборок, на которые имеются ссылки, но которые по какой-либо причине отсутствуют в текущем каталоге. Это невероятно полезно при использовании MEF. Возвращаемый список даст вам как отсутствующую сборку, так и того, кому она принадлежит (ее родитель)./// <summary> /// Intent: Get referenced assemblies, either recursively or flat. Not thread safe, if running in a multi /// threaded environment must use locks. /// </summary> 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<string, Assembly> _dependentAssemblyList; private static List<MissingAssembly> _missingAssemblyList; /// <summary> /// Intent: Get assemblies referenced by entry assembly. Not recursive. /// </summary> public static List<string> MyGetReferencedAssembliesFlat(this Type type) { var results = type.Assembly.GetReferencedAssemblies(); return results.Select(o => o.FullName).OrderBy(o => o).ToList(); } /// <summary> /// Intent: Get assemblies currently dependent on entry assembly. Recursive. /// </summary> public static Dictionary<string, Assembly> MyGetReferencedAssembliesRecursive(this Assembly assembly) { _dependentAssemblyList = new Dictionary<string, Assembly>(); _missingAssemblyList = new List<MissingAssembly>(); 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; } /// <summary> /// Intent: Get missing assemblies. /// </summary> public static List<MissingAssembly> MyGetMissingAssembliesRecursive(this Assembly assembly) { _dependentAssemblyList = new Dictionary<string, Assembly>(); _missingAssemblyList = new List<MissingAssembly>(); InternalGetDependentAssembliesRecursive(assembly); return _missingAssemblyList; } /// <summary> /// Intent: Internal recursive class to get all dependent assemblies, and all dependent assemblies of /// dependent assemblies, etc. /// </summary> 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]; } }обновление
чтобы сделать этот код потокобезопасным, поставить
lockвокруг него. В настоящее время он не является потокобезопасным по умолчанию, поскольку он ссылается на общую статическую глобальную переменную для выполнения своей магии.
получение загруженных сборок для текущего
AppDomain:var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();получение сборок, на которые ссылается другая сборка:
var referencedAssemblies = someAssembly.GetReferencedAssemblies();обратите внимание, что если сборка a ссылается на сборку B и сборку A загружена, это не означает, что сборка B также загружена. Сборка B будет загружена только в том случае, если и когда это необходимо. По этой причине
GetReferencedAssemblies()возвращаетAssemblyNameэкземпляров, а неAssemblyэкземпляров.
Comments