你如何通过当前加载的程序集循环? [英] How do you loop through currently loaded assemblies?

查看:172
本文介绍了你如何通过当前加载的程序集循环?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个诊断页面中,确实像验证数据库连接(S)我的ASP.NET应用程序,显示当前的appSettings和的ConnectionStrings,等这个页面的部分显示大会版本的重要用于整个的类型,但我无法弄清楚如何有效地显示所有加载的程序集的版本。

I've got a "diagnostics" page in my ASP.NET application which does things like verify the database connection(s), display the current appSettings and ConnectionStrings, etc. A section of this page displays the Assembly versions of important types used throughout, but I could not figure out how to effectively show the versions of ALL of the loaded assemblies.

什么是要弄清楚所有的当前引用和/或装载的最有效方法的在.NET应用程序组件?

What is the most effective way to figure out all currently referenced and/or loaded Assemblies in a .NET application?

注:我没有兴趣在基于文件的方法,如通过* .dll文件中的一个特定的目录遍历。我感兴趣的是什么应用实际上的使用的现在。

Note: I'm not interested in file-based methods, like iterating through *.dll in a particular directory. I am interested in what the application is actually using right now.

推荐答案

该扩展方法获取所有引用的程序集,递归,包括嵌套的组件。

This extension method gets all referenced assemblies, recursively, including nested assemblies.

由于它使用 ReflectionOnlyLoad ,它加载的程序集在一个单独的AppDomain中,它具有不与JIT过程干扰的优势。

As it uses ReflectionOnlyLoad, it loads the assemblies in a separate AppDomain, which has the advantage of not interfering with the JIT process.

您会发现,还有一个 MyGetMissingAssembliesRecursive 。你可以用它来检测被引用的任何程序集缺失,而不是present中由于某种原因当前目录。在使用 MEF 这是非常有用的。返回列表就会给你带来缺少的组件,以及谁拥有它(其父)。

You'll notice that there is also a MyGetMissingAssembliesRecursive. You can use this to detect any missing assemblies that are referenced, but not present in the current directory for some reason. This is incredibly useful when using MEF. The return list will give you both the missing assembly, and who owns it (its parent).

/// <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];
    }
}

更新

为了让这个code线程安全的,放了锁定周围。这不是当前线程安全的默认情况下,它引用了一个共享的静态全局变量做它的魔力。

Update

To make this code thread safe, put a lock around it. It's not currently thread safe by default, as it references a shared static global variable to do its magic.

这篇关于你如何通过当前加载的程序集循环?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆