Detecting whether a class descends from another class

View: New views
6 Messages — Rating Filter:   Alert me  

Detecting whether a class descends from another class

by Joe White-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


I want to iterate through AssemblyDefinition.MainModule.Types, and
identify which of those TypeDefinitions descend from a given base
class.

But I don't know how to walk a TypeDefinition's ancestry. I found
TypeDefinition.BaseType, which looks like it should get me from a
TypeDefinition to its base class. However, BaseType is of type
TypeReference, not TypeDefinition. TypeReference doesn't have a
BaseType, so I can't keep walking up the inheritance tree.

How can I write code that answers the question "does this
TypeDefinition descend from my known base class"?
--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---


Re: Detecting whether a class descends from another class

by Jonathan Pryor :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On Mon, 2009-08-17 at 11:33 -0700, Joe White wrote:
> But I don't know how to walk a TypeDefinition's ancestry. I found
> TypeDefinition.BaseType, which looks like it should get me from a
> TypeDefinition to its base class. However, BaseType is of type
> TypeReference, not TypeDefinition. TypeReference doesn't have a
> BaseType, so I can't keep walking up the inheritance tree.

The base type may belong to a different assembly, which is why it's a
TypeReference.  To obtain a TypeDefinition (to continue walking the
inheritance chain), you need to call TypeReference.Resolve():

        TypeDefinition type = ...;
        while (type != null) {
                // ...
                type = type.BaseType != null
                        ? type.Base.Resolve ()
                        : null;
        }

 - Jon



--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---


Re: Detecting whether a class descends from another class

by Joe White-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> To obtain a TypeDefinition (to continue walking the
> inheritance chain), you need to call TypeReference.Resolve():
> (snip)
>                 type = type.BaseType != null
>                         ? type.Base.Resolve ()
>                         : null;

Cool. That works, but only if the base class is in the same assembly.

But if I'm going through all the classes in my Tests assembly, and I
hit a class whose base class is in my Core assembly, I get a
FileNotFoundException from the Resolve() call, even though Core.dll is
in the same directory that I loaded Tests.dll from. This happens even
if I've previously loaded Core.dll from the AssemblyFactory, so
apparently it doesn't use already-loaded assemblies for resolution.

How do I get Resolve to resolve types in another assembly?
--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---


Re: Detecting whether a class descends from another class

by Jb Evain-2 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


On 8/18/09, Joe White <vulcanviking@...> wrote:
> Cool. That works, but only if the base class is in the same assembly.

Nope. Resolve, well, resolves, and if it need to open a new assembly, it will.

>  But if I'm going through all the classes in my Tests assembly, and I
>  hit a class whose base class is in my Core assembly, I get a
>  FileNotFoundException from the Resolve() call, even though Core.dll is
>  in the same directory that I loaded Tests.dll from. This happens even
>  if I've previously loaded Core.dll from the AssemblyFactory, so
>  apparently it doesn't use already-loaded assemblies for resolution.
>
>  How do I get Resolve to resolve types in another assembly?

It already does. It uses the .Resolver of the assembly to resolve the
assembly references, and then it will get you the definition inside
them.

--
Jb Evain  <jb@...>

--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---


Re: Detecting whether a class descends from another class

by Joe White-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


> Nope. Resolve, well, resolves, and if it need to open a new assembly, it will.

Yes, it looks like it's trying, hence the FileNotFoundException. But I
don't know where it's looking. Apparently not in the same directory
that the Tests assembly was loaded from, because the Core assembly is
right there and it's not finding it.

> It uses the .Resolver of the assembly to resolve the
> assembly references, and then it will get you the definition inside
> them.

Okay. How do I give it a .Resolver that will tell it to look in the
same directory that the Tests assembly was originally loaded from?
--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---


Re: Detecting whether a class descends from another class

by Joe White-6 :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message


Still stuck on this.

When I call Resolve() on a TypeReference, and the type reference is
from another assembly, Cecil tries to load that assembly. But I don't
know what directory it's trying to load it from. I expected it to look
in the same directory as the assembly I already loaded (and got the
TypeReference from), but it clearly doesn't. It just gives me a
FileNotFoundException.

How do I tell TypeReference.Resolve() what directory to look in when
it needs to load another assembly?
--~--~---------~--~----~------------~-------~--~----~
--
mono-cecil
-~----------~----~----~----~------~----~------~--~---