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

时间:2021-02-11 22:50:31

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.getassembly(),但是它只返回已经加载到内存中的程序集。

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

我尝试过Assembly.GetExecutingAssembly(). getreferencedassembly(),但它只返回mscorlib。

What am I missing?

我缺少什么?

3 个解决方案

#1


53  

Note that Assembly.GetReferencedAssemblies only 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.

注意,组装。getreferencedassembly只有在程序集中实际使用该程序集中的类型时才包含特定的程序集(或者使用的类型取决于该程序集中的类型)。仅仅在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 csproj file. For that, check out the ItemGroup element containing Reference elements.

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

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

最后,如果您知道程序集位于何处,可以使用程序集加载它。LoadFile,然后按上面的步骤对加载程序集中的类型进行枚举。

#2


0  

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
}

#3


0  

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

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

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和一个项目C正在引用项目B。现在您创建了一个新的项目a,它引用了C(而不是B)

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

当你叫组装。负载(“C路径”)。getreferenceassembly如果您从未对类、枚举、接口进行引用,它将只返回B。这是C大会的一部分。

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

就我个人而言,我使用这个解决方案是为了在核心项目中分离所有的接口和核心。Proj1将您的类标记为Core中使用的接口,以便以后在主程序集中发现。记住,在加载多个程序集之后,反射会对性能产生影响,所以不要以在目录上发现并加载所有程序集来获取所需类型的解决方案结束。因此,从那时起,您可以继续使用@jason建议的代码

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

#1


53  

Note that Assembly.GetReferencedAssemblies only 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.

注意,组装。getreferencedassembly只有在程序集中实际使用该程序集中的类型时才包含特定的程序集(或者使用的类型取决于该程序集中的类型)。仅仅在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 csproj file. For that, check out the ItemGroup element containing Reference elements.

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

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

最后,如果您知道程序集位于何处,可以使用程序集加载它。LoadFile,然后按上面的步骤对加载程序集中的类型进行枚举。

#2


0  

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
}

#3


0  

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

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

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和一个项目C正在引用项目B。现在您创建了一个新的项目a,它引用了C(而不是B)

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

当你叫组装。负载(“C路径”)。getreferenceassembly如果您从未对类、枚举、接口进行引用,它将只返回B。这是C大会的一部分。

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

就我个人而言,我使用这个解决方案是为了在核心项目中分离所有的接口和核心。Proj1将您的类标记为Core中使用的接口,以便以后在主程序集中发现。记住,在加载多个程序集之后,反射会对性能产生影响,所以不要以在目录上发现并加载所有程序集来获取所需类型的解决方案结束。因此,从那时起,您可以继续使用@jason建议的代码

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