JoshVarty JoshVarty - 4 months ago 11
C# Question

Find types that inherit from given INamedTypeSymbol

Given an

INamedTypeSymbol
(that comes from an referenced assembly, not source) how can I find all types (in both source and referenced assemblies) that inherit from this type?

In my particular case, I'm looking for all types that inherit from
NUnit.Framework.TestAttribute
. I can get access to the named type symbol as follows:

var ws = MSBuildWorkspace.Create();
var soln = ws.OpenSolutionAsync(@"C:\Users\...\SampleInheritanceStuff.sln").Result;
var proj = soln.Projects.Single();
var compilation = proj.GetCompilationAsync().Result;

string TEST_ATTRIBUTE_METADATA_NAME = "NUnit.Framework.TestAttribute";
var testAttributeType = compilation.GetTypeByMetadataName(TEST_ATTRIBUTE_METADATA_NAME);

//Now how do I find types that inherit from this type?


I've taken a look at
SymbolFinder
,
Compilation
and
INamedTypeSymbol
but I haven't had any luck.

Edit: The
FindDerivedClassesAsync
method looks close to what I need. (I'm not 100% sure that it finds derived classes in referenced assemblies). However it's internal, so I've opened an issue.

Answer

The FindDerivedClassesAsync is indeed what you are looking for.
It finds derived classes in referenced assemblies, as you can see in the source code for DependentTypeFinder (notice the locationsInMetadata variable).

As for using it, you can always do it with reflection in the meantime:

 private static readonly Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>> FindDerivedClassesAsync
            = new Lazy<Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>>(() => (Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>)Delegate.CreateDelegate(typeof(Func<INamedTypeSymbol, Solution, IImmutableSet<Project>, CancellationToken, Task<IEnumerable<INamedTypeSymbol>>>), DependentTypeFinder.Value.GetMethod("FindDerivedClassesAsync", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)));

(code borrowed from Tunnel Vision Laboratories Github)

Good luck!