如何通过Roslyn获取类的基类名称?

And*_*dry 4 c# roslyn

我正在使用Roslyn,我有以下课程:

var source = @"
    using System;
    class MyClass : MyBaseClass {
      static void Main(string[] args) {
        Console.WriteLine(""Hello, World!"");
      }
    }";

// Parsing
SyntaxTree tree = CSharpSyntaxTree.ParseText(source);

// This uses an internal function (working)
// That gets the first node of type `SimpleBaseTypeSyntax`
SimpleBaseTypeSyntax simpleBaseType = GetNBaseClassNode(tree);
Run Code Online (Sandbox Code Playgroud)

获取基类名称

我成功访问了SimpleBaseTypeSyntax包含我需要的节点.事实上,如果我使用语法资源管理器,我得到:

在此输入图像描述

节点IdentifierToken拥有我需要的一切都有Text,Value而且ValueText性能"MyBaseClass"!

但是,在语法资源管理器中,我可以看到所有这些值,我无法以编程方式访问它们.

所以我尝试以编程方式检索节点:

IdentifierNameSyntax identifierNode =
  simpleBaseType.ChildNodes().OfType<IdentifierNameSyntax>().First();
SyntaxToken identifier = simpleBaseType.Identifier;
string name = identifier.Text;
Run Code Online (Sandbox Code Playgroud)

但是name是空字符串.与identifier.Value和相同identifier.ValueText.

我究竟做错了什么?也许我做错了,那么你将如何检索基类名称呢?


另一种尝试:使用语义模型

我开始认为我需要这种类型信息的语义模型:

IdentifierNameSyntax identifierNode =
  simpleBaseType .ChildNodes().OfType<IdentifierNameSyntax>().First();

SemanticModel semanticModel =
  CSharpCompilation.Create("Class")
   .AddReferences(MetadataReference.CreateFromFile(
     typeof(object).Assembly.Location))
       .AddSyntaxTrees(tree).GetSemanticModel(tree);

SymbolInfo symbolInfo = this.semanticModel.GetSymbolInfo(identifierNode);
string name = symbolInfo.Symbol.Name;
Run Code Online (Sandbox Code Playgroud)

该抛出异常的symbolInfo.Symbol是null.

Jos*_*rty 9

我实际上不知道为什么你不能通过BaseTypeSyntax语义模型传递GetSymbolInfo(),但它也null为我返回没有错误.

无论如何,这是一种有效的方法:

var tree = CSharpSyntaxTree.ParseText(@"
using System;
class MyBaseClass
{
}
class MyClass : MyBaseClass {
  static void Main(string[] args) {
    Console.WriteLine(""Hello, World!"");
  }
}");

var Mscorlib = PortableExecutableReference.CreateFromAssembly(typeof(object).Assembly);
var compilation = CSharpCompilation.Create("MyCompilation",
    syntaxTrees: new[] { tree }, references: new[] { Mscorlib });
var model = compilation.GetSemanticModel(tree);

var myClass = tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>().Last();
var myClassSymbol = model.GetDeclaredSymbol(myClass);
var baseTypeName = myClassSymbol.BaseType.Name;
Run Code Online (Sandbox Code Playgroud)

您将在此处使用语义模型,因为您无法可靠地判断您是在语法级别处理接口还是基本类型.


Kev*_*non 6

我可以看到你正在尝试用Roslyn API构建一个分析器.您知道还有其他方法可以测试您的分析仪逻辑吗?使用单元测试文件而不是直接在分析器内部使用源.

使用这个想法,您可以使用Visual Studio提供的模板完全构建分析器,您必须从DiagnosticAnalyzer继承并创建分析代码逻辑.

根据您的情况,您应该查看ClassDeclaration并轻松访问Node内的BaseTypes属性.

        public bool SomeTriedDiagnosticMethod(SyntaxNodeAnalysisContext nodeContext)
    {
        var classDeclarationNode = nodeContext.Node as ClassDeclarationSyntax;
        if (classDeclarationNode == null) return false;
        var baseType = classDeclarationNode.BaseList.Types.FirstOrDefault(); //  Better use this in all situations to be sure code won't break
        var nameOfFirstBaseType = baseType.Type.ToString();  
        return nameOfFirstBaseType == "BaseType";

    }
Run Code Online (Sandbox Code Playgroud)