-
Notifications
You must be signed in to change notification settings - Fork 10
Resolving
The .net type system that you can manipulate through traditional Reflection erases the difference between a reference and a definition. It only provides you with resolved types, fields and methods. At the metadata level, and thus, at the Cecil level, we make a distinction between a reference and a definition.
They are both scoped per ModuleDefinition
. So, in a ModuleDefinition
, a definition is a metadata element defined in the module itself, and a reference is a metadata element defined in another module. For instance, if you have an assembly Foo.dll, which contains the type Foo.Bar
. This type Foo.Bar
exposes a method, Baz
that returns a System.String
.
If you load Foo.dll using Cecil, Foo.Bar
will be a TypeDefinition
, and the return type of the method Baz
will be a TypeReference
to System.String
. System.String
is defined in the assembly mscorlib.dll, which means that if you open mscorlib.dll with Cecil, there will be a System.String
TypeDefinition
in it.
The process of getting a definition from a reference is called resolving. All resolvable references in Cecil have Resolve
method. For instance, let’s say you have loaded Foo.dll in Cecil, and that you want to Resolve the return type of the Baz
method:
ModuleDefinition module = ModuleDefinition.ReadModule ("Foo.dll");
TypeDefinition foo_bar = module.Types.First (t => t.FullName == "Foo.Bar");
MethodDefinition baz = foo_bar.Methods.First (m => m.Name == "Baz");
TypeReference string_reference = baz.ReturnType;
// resolve into a definition:
TypeDefinition string_definition = string_reference.Resolve ();
ModuleDefinition corlib = string_definition.Module;
In this example, string_definition will be a TypeDefinition
, and its module will be the ModuleDefinition
for mscorlib.dll. To find the assembly that defines the reference, Cecil uses the IAssemblyResolver
of the ModuleDefinition
for Foo.dll.
We strongly suggest that you can specify your own IAssemblyResolver
when reading a ModuleDefinition
. This way you control the life-span of the module you load, and its associated references you resolve.
If you don’t specify a custom resolver, each module will have its own resolver, causing a greater memory usage.