简体   繁体   中英

Roslyn - Is a INamedTypeSymbol of a class or subclass of a given type

Using reflection, its pretty straightforward to determine whether an object is of a given class, using something like this:

(t == typeof(MyClass)) || (typeof(MyClass).IsAssignableFrom(t))

I'm trying to figure out how to do the same with Roslyn's code analysis APIs. I'm working with a loop like this, that attempts to find all local variable declarations in a solution.

foreach (var decl in rootNode.DescendantNodes().OfType<LocalDeclarationStatementSyntax>())
                {
                    var symbolInfo = semanticModel.GetSymbolInfo(decl.Declaration.Type);
                    var typeInfo = symbolInfo.Symbol as INamedTypeSymbol;
                    if (typeInfo == null)
                    {
                        continue;
                    }
                    // WHAT DO?

                }

I'm ultimately trying to build a list of all variables which are of a given type, or are of a subclass of a given type. It's easy enough to see how I could compare the name of the variable type to the name of the known type I am looking for - but I also need to handle the subclass case.

Is there a robust way to do this with Roslyn?

Within the Roslyn IDE codebase, we use this extension method . Note that you need be careful about whether you want to include just base types, or also interfaces. Also, do you care about generic instantiation?

您可以调用 compilation.ClassifyConversion(source, target)并检查结果的Kind是否为ConversionKind.ImplicitReference

I have a helper laying around from some time ago that checked for this. I haven't been up to date with Roslyn lately so someone might have to verify that this is (still) a proper solution.

Basically, once you have the INamedTypeSymbol you can check its BaseType property for the base class and its AllInterfaces property for all the interfaces it implements. I don't recall by heart whether the latter works on a semantic or syntactic level (as in: does it give you the interfaces that that specific type in the hierarchy implements or all interfaces in total). The name suggests the latter.

public static bool ImplementsInterfaceOrBaseClass(this INamedTypeSymbol typeSymbol, Type typeToCheck)
{
    if (typeSymbol == null)
    {
        return false;
    }

    if (typeSymbol.MetadataName == typeToCheck.Name)
    {
        return true;
    }

    if (typeSymbol.BaseType.MetadataName == typeToCheck.Name)
    {
        return true;
    }

    foreach (var @interface in typeSymbol.AllInterfaces)
    {
        if (@interface.MetadataName == typeToCheck.Name)
        {
            return true;
        }
    }

    return false;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM