Reputation: 8428
I have a .Net project where I'm given an assembly (*.dll
), and I have to list out the contained types and their members. However, I'm not given the assembly's references.
Suppose I'm given A.dll
which has a type in it:
public class TypeInA : IInterfaceInB
{
...
}
Since I'm not given B, I get a FileNotFoundException
when I try to call
typeof(TypeInA).GetInterfaces()
because it can't find B.dll
.
I don't need the details about IInterfaceInB
, just its namespace-qualified name. Is there a way I can get this without having to load B.dll
?
I'm following the MetadataLoadContext
docs to load A.dll
and enumerate its types:
var runtimeAssemblies = Directory.GetFiles(RuntimeEnvironment.GetRuntimeDirectory(), "*.dll");
var paths = new List<string>(runtimeAssemblies) {path};
var resolver = new PathAssemblyResolver(paths);
using var context = new MetadataLoadContext(resolver);
var assembly = context.LoadFromAssemblyPath(path);
Upvotes: 2
Views: 1063
Reputation: 3693
As provided by the Docs you posted as well
This collection, besides assemblies you want to inspect directly, should also include all needed dependencies. For example, to read the custom attribute located in an external assembly, you should include that assembly or an exception will be thrown.
Since you do not have B.dll
, I think it is normal that it throws an exception the moment you try to access any information in that assembly.
However, when I used ildasm.exe on A.dll, I could easily see the implemented interface(s)'s name(s). So It should be possible at least to get the names.
There is this decompiling library called dnlib
, which I use occasionally. Here is a sample code where you can read A.dll without having B.dll and moreover get Types' implemented interfaces FullName.
using System;
using System.Linq;
using dnlib.DotNet;
......
......
private static void Main(string[] args) {
// You need a module context in order to load an assembly
var moduleContext = ModuleDef.CreateModuleContext();
// This is the loaded module, please take note that it not loaded into your Domain
var loadedModule = ModuleDefMD.Load(@"A.dll", moduleContext);
var classes = loadedModule
.GetTypes() //You want types in this assembly
// I think you need classes, (structs too maybe?)
// But you do not need the Module
.Where(t=>t.IsClass && t.IsGlobalModuleType == false);
foreach (var typeDef in classes) {
Console.WriteLine($"{typeDef.FullName} implements:");
foreach (var typeDefInterface in typeDef.Interfaces) {
Console.WriteLine($" {typeDefInterface.Interface.FullName}");
}
}
Console.ReadKey();
}
Upvotes: 4