Check if ClassDeclarationSyntax implements a specific interface (Standalone code analysis tool)

Viewed 209

In my .NET 6 Standalone Code Analysis Tool I have a Compilation instance, a SemanticModel instance, and a ClassDeclarationSyntax instance.

I need to know if that class implements a specific interface (MediatR.IRequest<TRequest, TResponse>)

I can do it using string matching but I don't like that, is there a better way?

private static async Task AnalyzeClassAsync(Compilation compilation, SemanticModel model, ClassDeclarationSyntax @class)
{
    var baseTypeModel = compilation.GetSemanticModel(@class.SyntaxTree);

    foreach (var baseType in @class.BaseList.Types)
    {
        SymbolInfo symbolInfo = model.GetSymbolInfo(baseType.Type);
        var originalSymbolDefinition = (INamedTypeSymbol)symbolInfo.Symbol.OriginalDefinition;
        if (!originalSymbolDefinition.IsGenericType)
            return;
        if (originalSymbolDefinition.TypeParameters.Length != 2)
            return;

        if (originalSymbolDefinition.ToDisplayString() != "MediatR.IRequestHandler<TRequest, TResponse>")
            return;

        // Do other stuff here
    }
}
2 Answers

Getting a reference to the interface and then checking if the class implements it is a cleaner approach.

private static async Task AnalyzeClassAsync(Compilation compilation, SemanticModel model, ClassDeclarationSyntax @class)
{
    // MediatR.IRequestHandler`2 should be the fully qualified name
    // `2 indicates that the class/interface takes 2 type parameters
    var targetTypeSymbol = compilation.GetTypeByMetadataName("MediatR.IRequestHandler`2");

    // ...

    var implementsIRequestHandler = originalSymbolDefinition.AllInterfaces.Any(i => i.Equals(targetTypeSymbol))

   // Do other stuff here
}

I use this extension method:

public static class TypeExtensions
{
  public static bool IsAssignableToGenericType(this Type type, Type genericType)
  {
    if (type == null || genericType == null) return false;
    if (type == genericType) return true;
    if (genericType.IsGenericTypeDefinition && type.IsGenericType && type.GetGenericTypeDefinition() == genericType) return true;
    if (type.GetInterfaces().Where(it => it.IsGenericType).Any(it => it.GetGenericTypeDefinition() == genericType)) return true;
    return IsAssignableToGenericType(type.BaseType, genericType);
  }
}

use it like this:

var doesIt = typeof(MyClass).IsAssignableToGenericType(typeof(MediatR.IRequestHandler<,>)));
Related