.net 如何取得所有指涉组件的清单(已载入或未载入)

ufj5ltwl  于 2022-12-05  发布在  .NET
关注(0)|答案(3)|浏览(185)

我正在尝试为我加载到MEF中的主应用程序的程序集获取引用程序集的列表。
在运行插件之前,我想确保所有引用的程序集都存在于文件夹中。
我试过用

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

但是当我这样做时,它只显示在那个阶段使用/加载的程序集。我想要一个完整的程序集引用列表(在运行时)(VS中References文件夹的副本),而不管它们在那个时刻是否被使用。

oknwwptz

oknwwptz1#

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

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

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

dba5bblo

dba5bblo2#

您可以从文件元数据中提取这些信息。最快的方法可能是使用其中一个库来完成此操作。
例如,您可以使用Mono.Cecil
就像这样:

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

}
lyfkaqu1

lyfkaqu13#

我也在努力解决这个问题,并想出了Assembly.GetReferencedAssemblies()。这将给予你一个程序集中所有被引用的程序集。然而,要在整个应用程序中获得它们,你需要做一个传递闭包来获得引用所引用的程序集,等等。
这里有一个对我有用的函数。

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和System程序集--如果您继续使用这个“兔子”程序集,您将得到大量的程序集。但是,您可以根据需要进行调整。此外,我还 Package 了程序集。由于我的经验是,有时您会得到一些无法加载或不再使用的dll,因此将其加载到try/catch块中。同样,您可以随意处理这些程序集。
很明显,你需要传入你正在使用的顶级程序集、主程序或其他任何东西。你可以使用如下代码轻松调用它:

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

其中main是最上层组件中的型别。

相关问题