查找从不可用程序集中的类继承的DLL中的类。

时间:2022-09-25 12:33:10

I'm developing a tool that loads add-ins into a piece of commercial software we use in my office. Add-ins for this software can be developed by creating a .NET assembly with classes that inherit from classes in the software's API.

我正在开发一种工具,将插件加载到我们在办公室使用的一个商业软件中。这个软件的外接程序可以通过创建一个具有从软件API类中继承的类的。net程序集来开发。

So my software needs to inspect DLLs to determine if they contain classes which inherit from the API add-in classes by name. However, I don't want my application to depend on the API itself. It doesn't need to instantiate or execute any of these classes only determine the full names of classes which inherit from the API add-in classes.

因此,我的软件需要检查dll,以确定它们是否包含按名称从API外接程序继承的类。但是,我不希望我的应用程序依赖于API本身。它不需要实例化或执行这些类,只需要确定从API外接程序类继承的类的全部名称。

I am able to load the dll assembly using:

我可以使用以下方式加载dll程序集:

Assembly.LoadFrom(dllFileName)

Yet when I try to call GetTypes() on the loaded assembly. I get a ReflectionTypeLoadException with a number of LoaderExceptions complaining that the API files can not be found.

然而,当我试图在加载的程序集上调用GetTypes()时。我得到了一个反射类型的异常,有一些loaderexception异常抱怨API文件不能被找到。

I also tried using ReflectionOnlyLoadFrom() but it threw the same exception.

我也尝试过使用ReflectionOnlyLoadFrom(),但它也抛出了同样的异常。

Is there some other way to get this information? Again I don't need to execute any code, and ultimately I'd like my tool to work on a computer that doesn't have the API or software installed at all. All I need to know is the full classes names.

还有其他方法来获取这些信息吗?同样,我不需要执行任何代码,最终我希望我的工具可以在没有安装API或软件的计算机上工作。我只需要知道完整的类名。

2 个解决方案

#1


0  

This cannot be done using the framework's Reflection API. Reflection requires access to the assemblies to load the type metadata. What you could do is use something like Mono.Cecil (available on nuget) to inspect the MSIL. Here is a sample showing types with base classes and interfaces in an assembly:

这不能用框架的反射API来完成。反射需要访问程序集来加载类型元数据。你所能做的就是使用像Mono这样的东西。塞西尔(在nuget上可用)检查MSIL。下面是一个示例,展示了在一个程序集中的基类和接口:

using Mono.Cecil;
using Mono.Cecil.Cil;

var assembly = AssemblyDefinition.ReadAssembly("ClassLibrary.dll");
// skip the first type '<Module>' whatever that is.
var types = assembly.MainModule.Types.Skip(1);

foreach (var type in types)
{
    var interfaces = type.Interfaces.Select(i => i.FullName);
    if (interfaces.Any())
    {
         Console.WriteLine("{0} : {1}, {2}", type.FullName, type.BaseType.FullName, string.Join(", ", interfaces));
    }
    else
    {
         Console.WriteLine("{0} : {1}", type.FullName, type.BaseType.FullName);
    }
}

This does not cause the assembly or any of its dependencies to be loaded. This would be useful when you know the classes you are interested in are directly inherited from the foreign API classes. If there are several levels of inheritance then you will have to do more work than I've shown above.

这不会导致程序集或它的任何依赖项被加载。当您知道您感兴趣的类直接从外部API类继承时,这将非常有用。如果有几个级别的继承,那么您将不得不做比我上面显示的更多的工作。

#2


0  

It is not possible using Reflection. If you are just interested in looking for dependencies, you can use ObjectExplorer to view the classes in DLL assembly and see their base types. And look for types that does not belong to the same assembly.

使用反射是不可能的。如果您只是想寻找依赖关系,那么可以使用ObjectExplorer查看DLL程序集中的类,并查看它们的基本类型。寻找不属于同一程序集的类型。

You can find some useful information here:
Which program in Visual Studio lets me look into DLLs to see its API?

您可以在这里找到一些有用的信息:Visual Studio中的哪个程序可以让我查看dll来查看它的API?

#1


0  

This cannot be done using the framework's Reflection API. Reflection requires access to the assemblies to load the type metadata. What you could do is use something like Mono.Cecil (available on nuget) to inspect the MSIL. Here is a sample showing types with base classes and interfaces in an assembly:

这不能用框架的反射API来完成。反射需要访问程序集来加载类型元数据。你所能做的就是使用像Mono这样的东西。塞西尔(在nuget上可用)检查MSIL。下面是一个示例,展示了在一个程序集中的基类和接口:

using Mono.Cecil;
using Mono.Cecil.Cil;

var assembly = AssemblyDefinition.ReadAssembly("ClassLibrary.dll");
// skip the first type '<Module>' whatever that is.
var types = assembly.MainModule.Types.Skip(1);

foreach (var type in types)
{
    var interfaces = type.Interfaces.Select(i => i.FullName);
    if (interfaces.Any())
    {
         Console.WriteLine("{0} : {1}, {2}", type.FullName, type.BaseType.FullName, string.Join(", ", interfaces));
    }
    else
    {
         Console.WriteLine("{0} : {1}", type.FullName, type.BaseType.FullName);
    }
}

This does not cause the assembly or any of its dependencies to be loaded. This would be useful when you know the classes you are interested in are directly inherited from the foreign API classes. If there are several levels of inheritance then you will have to do more work than I've shown above.

这不会导致程序集或它的任何依赖项被加载。当您知道您感兴趣的类直接从外部API类继承时,这将非常有用。如果有几个级别的继承,那么您将不得不做比我上面显示的更多的工作。

#2


0  

It is not possible using Reflection. If you are just interested in looking for dependencies, you can use ObjectExplorer to view the classes in DLL assembly and see their base types. And look for types that does not belong to the same assembly.

使用反射是不可能的。如果您只是想寻找依赖关系,那么可以使用ObjectExplorer查看DLL程序集中的类,并查看它们的基本类型。寻找不属于同一程序集的类型。

You can find some useful information here:
Which program in Visual Studio lets me look into DLLs to see its API?

您可以在这里找到一些有用的信息:Visual Studio中的哪个程序可以让我查看dll来查看它的API?