问题
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?
回答1:
Ah, that makes sense. An ITypeElement
is an instance of IDeclaredElement
, which means it's something that has a declaration - such as a class or interface declaration. So when you get an IType
that represents your closed generic, it's made up of an ITypeElement
that represents the generic type (ICommandHandler
) and an ISubstitution
that represents the resolved generic type parameters (AnotherCommand
). When you call IType.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. The FindResult
passed to the consumer can be downcast to a FindResultInheritedElement
, which will give you a declared element that represents the class that implements ITypeHandler<T>
. You should be able to walk these elements' interfaces to see what they implement, and only accept those find results that implement the correct T
. I think TypeElementUtil
will help here to get all super types (base types + interfaces) of the declared element.
来源:https://stackoverflow.com/questions/31044308/how-do-i-create-a-itypeelement-with-represents-a-closed-generic-type-in-a-resh