繁体   English   中英

如何获取所有引用程序集的列表(已加载或未加载)

[英]How to get a list of all referenced assemblies (loaded or not)

我正在尝试获取我加载到 MEF 主应用程序中的程序集的引用程序集列表。

在运行插件之前,我想确保所有引用的程序集都存在于文件夹中。

我尝试使用

List<AssemblyName> a = Assembly.GetEntryAssembly().GetReferencedAssemblies().ToList();

但是当我这样做时,它只显示在那个阶段使用/加载的程序集。 我想要一个完整的列表(在运行时)引用的程序集(VS 中引用文件夹的副本),无论它们是在那个时候使用还是根本没有使用。

在加载插件之前,您可以加载它仅用于反射,只加载文件的元数据。 例如:

    var assm = Assembly.ReflectionOnlyLoadFrom(@"Same.dll");
    var reff = assm.GetReferencedAssemblies();

请记住,关联的库可以有他们的引用。

您可以从文件元数据中提取该信息。 最快的方法可能就是使用其中一个库来实现。

例如,您可以使用Mono.Cecil

像这样:

var md = ModuleDefinition.ReadModule(assemblyPath);
foreach (var reference in md.AssemblyReferences)
{

}

我也在为此苦苦挣扎,想出了Assembly.GetReferencedAssemblies() 这将为您提供程序集中所有引用的程序集。 但是,要在整个应用程序中获取它们,您需要执行传递闭包以获取引用等引用的程序集。

这是对我有用的 function。

    private static List<Assembly> GetAllReferencedAssemblies(Assembly asm)
    {
        var nameQueue = new Queue<AssemblyName>(asm.GetReferencedAssemblies());
        var alreadyProcessed = new HashSet<string>() { asm.FullName };
        var result = new List<Assembly>();
        result.Add(asm);
        while (nameQueue.Any())
        {
            var name = nameQueue.Dequeue();
            var fullName = name.FullName;
            if (alreadyProcessed.Contains(fullName) || fullName.StartsWith("Microsoft.") || fullName.StartsWith("System."))
                continue;
            alreadyProcessed.Add(fullName);
            try
            {
                var newAssembly = Assembly.Load(name);
                result.Add(newAssembly);
                foreach (var innerAsmName in newAssembly.GetReferencedAssemblies())
                    nameQueue.Enqueue(innerAsmName);
                Debug.WriteLine(name);
            }
            catch (Exception e)
            {
                Debug.WriteLine(e);
            }
        }

        return result;
    }

几个实用的要点:你会看到我添加了一行来排除 Microsoft 和系统程序集——如果你 go 整个兔子,你会得到大量的程序集。 但是,您可以根据需要进行调整。 此外,我将 Assembly.Load 包装在一个 try/catch 块中,因为我的经验是有时您会得到一些无法加载或不再使用的 dll。 再次强调,您可以随心所欲地使用它。

显然对你来说,你传递了你正在使用的顶级程序集,主程序或其他任何东西。 您可以使用以下内容轻松调用它:

var asmList = GetAllReferencedAssemblies(typeof(Main).Assembly);

其中main是顶级程序集中的一种类型。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM