如何获取引用程序集中的所有类型?

44

无论出于何种原因,我似乎无法获取已引用程序集中的类型列表。更糟的是,我甚至无法访问这个已引用的程序集。

我尝试使用AppDomain.CurrentDomain.GetAssemblies(),但它只返回已加载到内存中的程序集。

我也尝试了Assembly.GetExecutingAssembly().GetReferencedAssemblies(),但这只会返回mscorlib。

我错过了什么吗?


1
你是想检查项目引用的程序集,还是想检查文件系统中某个位置上的程序集? - user47589
1
我怀疑CLR的实现会使得从所有程序集中获取所有类型变得不可能,因为它们必须在一个紧迫的时间内进行即时编译,但我并不是专家,所以你应该把我的评论仅作为进一步探索的提示。 - zneak
@yodaj007 引用的程序集 - AngryHacker
@itowlson 我的代码是一个全新的控制台项目,我引用了一个我想要检查的程序集。就这些。 - AngryHacker
3个回答

74
请注意,Assembly.GetReferencedAssemblies 方法只会在您的程序集中使用了特定程序集中的类型(或者您使用的类型依赖于该程序集中的类型)时,才会包括该特定程序集。仅仅在 Visual Studio 的引用列表中添加程序集并不足够。也许这就解释了你期望的输出结果与实际输出结果之间的差异?需要指出的是,如果你希望使用反射来获取 Visual Studio 引用列表中所有程序集,那是不可能的;给定程序集的元数据不包括任何有关它不依赖的程序集的信息。
话虽如此,一旦您检索到所有引用程序集的列表,以下代码段将允许您枚举这些程序集中的所有类型:
foreach (var assemblyName in Assembly.GetExecutingAssembly().GetReferencedAssemblies()) {
    Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in assembly.GetTypes()) {
        Console.WriteLine(type.Name);
    }
}

如果您需要在Visual Studio中引用的程序集,则必须解析csproj文件。为此,请查看包含Reference元素的ItemGroup元素。

最后,如果您知道程序集位于何处,则可以使用Assembly.LoadFile加载它,然后基本上按照上述方法枚举驻留在该已加载程序集中的类型。


在我的情况下,如果我从未使用汇编语言,即使在项目中有引用,它也不会被包含! - Tono Nam

5

我也遇到了一个情况,需要获取在Visual Studio的引用列表中的所有程序集。

我使用以下方法解决了这个问题。

var path = AppContext.BaseDirectory;  // returns bin/debug path
var directory = new DirectoryInfo(path);

if (directory.Exists)
{
    var dllFiles = directory.GetFiles("*.dll");  // get only assembly files from debug path
}

这似乎是一个合理的解决方案。 - jwrightmail

0
方法GetReferencedAssemblies主要优化您的程序集发现过程,跳过那些您在主要程序集中没有明确引用的程序集。
假设您有项目B和引用了项目B的项目C。现在您创建了一个新项目A,该项目引用C(而不是B)。
当您调用Assembly.Load("C path").GetReferenceAssemblies时,它将只返回B,如果您从未引用过C程序集中的类、枚举、接口等内容。
作为解决方案的变通方法,您可以创建存在于C中的类的虚拟实例。
Assembly.C.Class1 dummyInstance = new Assemply.C.Class1();

就个人而言,如果您需要在核心项目中分离出所有接口,并在Core.Proj1中为稍后在主要程序集中发现所用的接口标记类,则可以使用此解决方案。请注意,一旦加载了多个程序集,反射会对性能产生影响,因此不要以一种在目录上进行发现并加载所有程序集以获取所需类型的解决方案结束。因此,您可以继续使用@jason建议的代码

foreach(var ....)
  Assembly assembly = Assembly.Load(assemblyName);
    foreach (var type in assembly.GetTypes()) {
        Console.WriteLine(type.Name);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接