Using CilTools.Metadata
CilTools.Metadata library enables you to inspect the contents of .NET assemblies without loading them to the execution context. The assemlies are inspected using the same API surface as standard reflection, but operating on artificial informational-only System.Reflection.Assembly
instances, though some reflection API are not available on them. These instances can be unloaded from memory using Dispose
method when they are no longer needed.
With CilTools.Metadata you can load assemblies for another target framework, or assemblies with unresolved dependencies, but if some member references an external member which is not available, you might be unable to read information about that missing member. For example, if the field type is declared in the missing assembly, you will be able to read the name of that type, but not the list of its members.
Prerequisites
To use CilTools.Metadata, install CilTools.Metadata NuGet package. You can also build the library from sources or download released binaries in CIL Tools repository. The minimum target framework is .NET Framework 4.5 or .NET Standard 2.0.
Enumerating methods in an assembly
To read assembly information, use AssemblyReader class. It provides Load
and LoadFrom
methods that returns Assembly
instances for a given assembly name or file path, respectively. Then you can work with these assemblies using regular reflection methods, such as Assembly.GetTypes
. When you no longer need loaded assemblies, release them with Dispose
method or using
block.
To enumerate methods in the given type, use Type.GetMembers
method and filter out methods from the returned list. The returned method instances derive from MethodBase
class and implement ICustomMethod
interface. Type.GetMethods
and Type.GetConstructors
are not supported.
The following example shows how to display methods from the given assembly:
using System;
using System.Reflection;
using CilTools.Metadata;
//...
static void PrintMethods(string assemblyPath)
{
AssemblyReader reader = new AssemblyReader();
using (reader)
{
Assembly ass = reader.LoadFrom(assemblyPath);
Type[] types = ass.GetTypes();
for(int n=0;n<types.Length;n++)
{
Type t = types[n];
MemberInfo[] members = t.GetMembers(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance
);
for (int i = 0; i < members.Length; i++)
{
if (members[i] is MethodBase)
{
Console.WriteLine(t.Name+"."+members[i].Name);
}
}
}
}
}
Getting P/Invoke parameters for the unmanaged method
To get P/Invoke parameters for the method imported from unmanaged library, such as a DLL name or calling convention, use the GetPInvokeParams() method. The following example displays P/Invoke information for all unmanaged methods in the given assembly:
using System;
using System.Reflection;
using CilTools.Metadata;
using CilTools.Reflection;
//...
static void PrintPInvokeParams(string assemblyPath)
{
AssemblyReader reader = new AssemblyReader();
using (reader)
{
Assembly ass = reader.LoadFrom(assemblyPath);
Type[] types = ass.GetTypes();
for (int n = 0; n < types.Length; n++)
{
Type t = types[n];
MemberInfo[] members = t.GetMembers(
BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static | BindingFlags.Instance
);
for (int i = 0; i < members.Length; i++)
{
if (members[i] is ICustomMethod && members[i] is MethodBase &&
((MethodBase)members[i]).Attributes.HasFlag(MethodAttributes.PinvokeImpl))
{
PInvokeParams pars = ((ICustomMethod)members[i]).GetPInvokeParams();
Console.WriteLine(t.Name + "." + members[i].Name);
Console.WriteLine("Module: "+pars.ModuleName);
Console.WriteLine("Calling convention: " + pars.CallingConvention.ToString());
}
}
}
}
}
See also
CilTools.Metadata API reference
Assemblies in .NET on Microsoft Docs