I'm using Mono.Cecil to find types in Assembly that are derived from given on. Normaly it can be done with IsAssignableFrom() method, but I cannot fing it's equivalent in Cecil. Is there any such method or other way to check it? Thanks Mike
-
I think I remember seeing a 'Rock' for that – sehe May 10 '11 at 06:48
4 Answers
Inheritance checks and "assignment compatibility" checks are actually different things. Do you want to check inheritance or "assignment compatibility"?
Assignment compatibility includes a lot of things, including signed / unsigned conversions, enum to base type conversions, char
to short
conversions, generic variance conversions, conversions from interfaces to object
, from arrays to IList
and IList<T>
and their base interfaces, array covariance, generic parameter to constraints, and a whole bunch of other stuff.
Your best bet is to lookup the assignment compatability and "verification type compatibility" rules int the ECMA spec for a complete list.
I'm guessing for your particular needs you'll want some subset of the full "assignment compatibility checks".
Unfortunately, Cecil doesn't have any methods that will implement this for you, but it does provide enough information for you to implement this your self.
You do need to be careful when implementing something like this using cecil. In particular the TypeReference class has a "Resolve" method that you need to call in some cases (for finding the TypeDefinition for an unresolved type reference), but that you can't call in other cases, because it will dig too far through the type tree. You'll also need to deal with "structural type equality" for comparing generic instantations, and will have to handle generic parameter substitution when walking up type hierarchies.

- 24,561
- 8
- 60
- 89
-
1+1. It would be nice to see some code examples. Of course, without detailed requirements it's hard to recommend a specific approach (as your answer explains). – Merlyn Morgan-Graham May 10 '11 at 06:35
-
I have code that does this... but I can't share it with you...(at least not now). The main points I wanted to convey where that: 1) Assignment compatibility covers more than inheritance, 2) Inheritance checks require checking more things than you may have thought, 3) Everything you need to consider is listed in the ECMA spec, 4) There are some pitfalls in the cecil API you need to be careful of. I can't give you code though. – Scott Wisniewski May 10 '11 at 06:41
-
No worries. Reflections/low level type manipulation is hard, and having help for common cases would be nice for purposes of this answer (as well as for Cecil itself). This answer is still useful how it is :) – Merlyn Morgan-Graham May 10 '11 at 06:46
I've never done anything with Mono, let alone Cecil, but looking through the GitHub source, I'm guessing you could probably do something with a TypeDefinition
of the type:
public bool HasInterface(TypeDefinition type, string interfaceFullName)
{
return (type.Interfaces.Any(i => i.FullName.Equals(interfaceFullName))
|| type.NestedTypes.Any(t => HasInterface(t, interfaceFullName)));
}

- 60,571
- 9
- 104
- 129
-
+1. When I did a project using Cecil, I thought about adding a feature request for something that wrapped this type of functionality, but never got around to it :) Also, I forget why, and in which cases, but you might have to do null checks for some of these properties before enumerating them... – Merlyn Morgan-Graham May 10 '11 at 06:32
One method to find derived types of type AType is to enumerate all types defined in the assembly and compare their BaseType property to the type AType. This method is used in ILSpy to show derived types of a selected type. Implementation is in FindDerivedTypes method (DerivedTypesTreeNode.cs). To find types derived indirectly you have to iterate over BaseType property (using Resolve()) until the AType is reached or BaseType is equal to null.

- 63
- 5
The ApiChange tool does use Mono Cecil. It can find all occurences where your type is used including derivation from your type with the command
ApiChange.exe -whousestype "CommandBase" ApiChange.Api.dll -in ApiChange.Api.dll -excel
you will get an Excel output with file and line number of all users of your type. It looks like
ApiChange.Api.dll internal class ApiChange.Api.Scripting.CorFlagsCommand Inherits from internal class ApiChange.Api.Scripting.CommandBase C:\Source\ApiChangeTooling\ApiChange.Api\src\Scripting\Commands\CorFlagsCommand.cs
ApiChange.Api.dll internal class ApiChange.Api.Scripting.WhoImplementsInterfaceCommand Inherits from internal class ApiChange.Api.Scripting.CommandBase C:\Source\ApiChangeTooling\ApiChange.Api\src\Scripting\Commands\WhoImplementsInterfaceCommand.cs
ApiChange.Api.dll internal class ApiChange.Api.Scripting.DiffAssembliesCommand Inherits from internal class ApiChange.Api.Scripting.CommandBase C:\Source\ApiChangeTooling\ApiChange.Api\src\Scripting\Commands\DiffAssembliesCommand.cs
The actual code using Cecil is located in WhoUsesType.cs
Yours, Alois Kraus

- 13,229
- 1
- 38
- 64