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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2241961/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:40:58  来源:igfitidea点击:

How to get all types in a referenced assembly?

c#.netreflectionassembliesreference

提问by AngryHacker

For whatever reason, I can't seem to get the list of types in a referenced assembly. Not only that, I can't even seem to be able to get to this referenced assembly.

无论出于何种原因,我似乎无法获得引用程序集中的类型列表。不仅如此,我什至无法访问这个引用的程序集。

I tried AppDomain.CurrentDomain.GetAssemblies(), but it only returns assemblies that have already been loaded into memory.

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

I tried Assembly.GetExecutingAssembly().GetReferencedAssemblies(), but this just returns mscorlib.

我试过了Assembly.GetExecutingAssembly().GetReferencedAssemblies(),但这只是返回 mscorlib。

What am I missing?

我错过了什么?

采纳答案by jason

Note that Assembly.GetReferencedAssembliesonly includes a particular assembly if you actually use a type in that assembly in your assembly (or a type that you use depends on a type in that assembly). It is not enough to merely include an assembly in the list of references in Visual Studio. Maybe this explains the difference in output from what you expect? I note that if you're expecting to be able to get all the assemblies that are in the list of references in Visual Studio using reflection that is impossible; the metadata for the assembly does not include any information about assemblies on which the given assembly is not dependent on.

请注意,Assembly.GetReferencedAssemblies如果您在程序集中实际使用该程序集中的类型(或您使用的类型取决于该程序集中的类型),则仅包含特定程序集。仅在 Visual Studio 的引用列表中包含一个程序集是不够的。也许这解释了输出与您期望的差异?我注意到,如果您希望能够使用反射获取 Visual Studio 中引用列表中的所有程序集,这是不可能的;程序集的元数据不包括有关给定程序集不依赖的程序集的任何信息。

That said, once you've retrieved a list of all the referenced assemblies something like the following should let you enumerate over all the types in those assemblies:

也就是说,一旦您检索到所有引用程序集的列表,如下所示应该让您枚举这些程序集中的所有类型:

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

If you need the assemblies that are referenced in Visual Studio then you will have to parse the csprojfile. For that, check out the ItemGroupelement containing Referenceelements.

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

Finally, if you know where an assembly lives, you can load it using Assembly.LoadFileand then essentially proceed as above to enumerate over the types that live in that loaded assembly.

最后,如果您知道程序集所在的位置,则可以使用加载它Assembly.LoadFile,然后基本上按照上述步骤枚举该加载程序集中的类型。

回答by Deepak Ageeru

I also landed in a situation where I had to get all the assemblies that are in the list of references in Visual Studio.

我还遇到了一种情况,我必须获取 Visual Studio 中引用列表中的所有程序集。

I used following work around to get it done.

我使用以下工作来完成它。

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
}

回答by Zinov

The method GetReferencedAssembliesbasically optimize the discovery process on your assembly, skipping those assemblies that you don't have an explicit reference in your main assembly.

GetReferencedAssemblies方法基本上优化了程序集上的发现过程,跳过了主程序集中没有显式引用的那些程序集。

Let's say that you have a project B and a project C that is referencing project B. Now you create a new project A that has a reference to C(not to B)

假设您有一个项目 B 和一个引用项目 B 的项目 C。现在您创建一个引用 C(而不是 B)的新项目 A

When you call Assembly.Load("C path").GetReferenceAssembliesit will return just B if you never made a reference to a class, enum, interface ... that was part of the C assembly.

Assembly.Load("C path").GetReferenceAssemblies如果您从未引用过类、枚举、接口……那是 C 程序集的一部分,那么当您调用它时,它只会返回 B。

As a workaround solution, you can create dummies instances of classes that are present in C.

作为一种变通解决方案,您可以创建 C 中存在的类的虚拟实例。

Assembly.C.Class1 dummyInstance = new Assemply.C.Class1();

Personally, I used this solution in case you need to separate in a Core project all your interfaces, and in Core.Proj1 to flag your classes with the interfaces used in Core for a later discovery in your main assembly. Take in mind that reflection has an impact on the performance once you are loading multiple assemblies, so don't end with a solution making a discovery on a directory and loading all assemblies to get the types you need. So from that point, you can continue with the code that @jason suggested

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

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