23

Is there anyways to go from a TypeReference in Mono.Cecil to a Type?

Will
  • 10,013
  • 9
  • 45
  • 77

2 Answers2

24

In terms of "what's in the box" you can only have it the other way round, using the ModuleDefinition.Import API.

To go from a TypeReference to a System.Type you will need to manually look it up using Reflection and the AssemblyQualifiedName. Be aware that Cecil uses IL conventions to escape nested classes etc, so you need to apply some manual correction.

If you only want to resolve non-generic, non-nested types you should be fine though.

To go from a TypeReference to a TypeDefition (if that's what you meant) you need to to TypeReference.Resolve();


Requested Code Sample:

TypeReference tr = ... 
Type.GetType(tr.FullName + ", " + tr.Module.Assembly.FullName); 
// will look up in all assemnblies loaded into the current appDomain and fire the AppDomain.Resolve event if no Type could be found

The conventions used in Reflection are explained here, for Cecils conventions consult the Cecil Source Code.

Oli
  • 830
  • 7
  • 20
Johannes Rudolph
  • 35,298
  • 14
  • 114
  • 172
  • Also note that Mono.Cecil is NOT built over System.Reflection (being an independent library), that means that there's no direct way to convert them to each other. You should still be able to do that, but it won't look nice. – ShdNx Nov 15 '10 at 13:07
  • So how with reflection would I lookup the type? And do you have an example of a reflection nested type and a cecil nested type? – Will Nov 15 '10 at 15:57
  • 7
    Instead of manually adding ", ", you can use Assembly.CreateQualifiedName(tr.Module.Assembly.FullName, tr.FullName). – user276648 May 29 '12 at 08:59
  • provided code doesn't work for generic types because Cecil uses "ClassName" notation when .Net Reflection expects "ClassName[[gen_arg_0],...] notation. – Andriy Tylychko Jul 29 '14 at 12:01
  • @AndyT: Yes, that's just one of the many cases where the notation differs. Thanks for your sample. – Johannes Rudolph Jul 31 '14 at 08:27
  • 1
    Is there a way to go in the opposite direction? From System.Type to Mono.Cecil.TypeDefinition? – John Zabroski Apr 13 '15 at 20:23
  • 1
    @JohnZabroski you have to do something like this: `var assemblyDefinition = AssemblyDefinition.ReadAssembly(type.Assembly.Location,params); var resolverType = assemblyDefinition.MainModule.Types.SingleOrDefault(t=>t.Name == type.Name);` – n.podbielski May 10 '18 at 12:31
  • Yes, i ended up with that – John Zabroski May 11 '18 at 18:40
2

For generic types you need something like this:

    public static Type GetMonoType(this TypeReference type)
    {
        return Type.GetType(type.GetReflectionName(), true);
    }

    private static string GetReflectionName(this TypeReference type)
    {
        if (type.IsGenericInstance)
        {
            var genericInstance = (GenericInstanceType)type;
            return string.Format("{0}.{1}[{2}]", genericInstance.Namespace, type.Name, String.Join(",", genericInstance.GenericArguments.Select(p => p.GetReflectionName()).ToArray()));
        }
        return type.FullName;
    }

Please note this code doesn't handle nested types, please check @JohannesRudolph answer for this

Andriy Tylychko
  • 15,967
  • 6
  • 64
  • 112