Roslyn - 是给定类型的类或子类的 INamedTypeSymbol

kc9*_*ddi 4 c# roslyn

使用反射,确定一个对象是否属于给定类非常简单,使用如下所示:

(t == typeof(MyClass)) || (typeof(MyClass).IsAssignableFrom(t))
Run Code Online (Sandbox Code Playgroud)

我试图弄清楚如何使用 Roslyn 的代码分析 API 来做同样的事情。我正在使用这样的循环,它试图在解决方案中找到所有局部变量声明。

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?

                }
Run Code Online (Sandbox Code Playgroud)

我最终试图构建一个包含给定类型或给定类型的子类的所有变量的列表。很容易看出我如何将变量类型的名称与我正在寻找的已知类型的名称进行比较 - 但我还需要处理子类情况。

有没有一种强大的方法可以用 Roslyn 做到这一点?

SLa*_*aks 5

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


Kev*_*lch 5

在 Roslyn IDE 代码库中,我们使用此扩展方法。请注意,您需要注意是只包含基本类型还是接口。另外,你关心泛型实例化吗?

  • 我们需要包含哪些程序集才能获得此扩展方法? (2认同)
  • 链接已损坏。我不确定该方法现在是否仍在同一个类中:https://github.com/dotnet/roslyn/blob/e18704cc41c1fdb90f9bfda0b27cde6447adb583/src/Compilers/CSharp/Portable/Utilities/TypeSymbolExtensions.cs 您可以发布一个更新? (2认同)

Jer*_*vel 4

我有一个助手从前一段时间开始检查这一点。我最近没有了解罗斯林的最新情况,所以有人可能必须验证这(仍然)是一个正确的解决方案。

基本上,一旦您拥有了,INamedTypeSymbol您就可以检查其BaseType基类的属性及其AllInterfaces实现的所有接口的属性。我记不清后者是否在语义或语法级别上起作用(例如:它是否为您提供了层次结构中特定类型实现的接口或总共的所有接口)。顾名思义,是后者。

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;
}
Run Code Online (Sandbox Code Playgroud)