I'm using the ReSharper 8 sdk and want to find all inheritors of a particular generic interface, where the generic type is a particular type. I have asked a more general question which got most of the way there, but I am only able to find any implementation of ICommandHandler<T>
and not the one implementation I want, ICommandHandler<TestCommand>
this is the code I have:
foreach (var psiModule in declaredElement.GetPsiServices().Modules.GetModules())
{
IDeclaredType genericType = TypeFactory.CreateTypeByCLRName("HandlerNavigationTest.ICommandHandler`1", psiModule, theClass.ResolveContext);
var genericTypeElement = genericType.GetTypeElement();
if (genericTypeElement != null)
{
var theType = TypeFactory.CreateType(originalTypeElement);
var commandHandlerType = TypeFactory.CreateType(genericTypeElement,theType);
var handlerTypeelement = commandHandlerType.GetTypeElement();
solution.GetPsiServices().Finder.FindInheritors(handlerTypeelement, searchDomainFactory.CreateSearchDomain(solution, true),
inheritorsConsumer, NullProgressIndicator.Instance);
var inheritedInstance= inheritorsConsumer.FoundElements.First();
var sourceFile = inheritedInstance.GetSourceFiles().First();
}
}
if I tooltip the commandHandlerType after this line:
var commandHandlerType = TypeFactory.CreateType(genericTypeElement,theType);
I see that the type is correctly specified:
But then when I get the ITypeElement
from this type to pass into my search using this line
var handlerTypeelement = commandHandlerType.GetTypeElement();
I seem to have lost the type:
And so my search finds all implementations of the ICommandHandler<T>
.
So my question is, how do I create the ITypeElement
which represents the closed generic type I want to search for?
Or alternatively: How can I search the returned collection of inheritors for the type which has the class I started with as the generic type parameter?
Ah, that makes sense. An
ITypeElement
is an instance ofIDeclaredElement
, which means it's something that has a declaration - such as a class or interface declaration. So when you get anIType
that represents your closed generic, it's made up of anITypeElement
that represents the generic type (ICommandHandler
) and anISubstitution
that represents the resolved generic type parameters (AnotherCommand
). When you callIType.GetTypeElement()
, it will return the type element part of the type element/substitution pair, which is the open generic declared element (because an interface declaration can only ever be open).I think you might have to take the alternative approach, and find all inheritors (implementors) of
ITypeHandler<T>
and filter them down in the consumer. TheFindResult
passed to the consumer can be downcast to aFindResultInheritedElement
, which will give you a declared element that represents the class that implementsITypeHandler<T>
. You should be able to walk these elements' interfaces to see what they implement, and only accept those find results that implement the correctT
. I thinkTypeElementUtil
will help here to get all super types (base types + interfaces) of the declared element.