C# 如何通过Roslyn获取类的基类名称?
我正在使用,我有以下课程:C# 如何通过Roslyn获取类的基类名称?,c#,roslyn,C#,Roslyn,我正在使用,我有以下课程: var source = @" using System; class MyClass : MyBaseClass { static void Main(string[] args) { Console.WriteLine(""Hello, World!""); } }"; // Parsing SyntaxTree tree = CSharpSyntaxTree.ParseText(source);
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);
获取基类名称
我成功地访问了包含我所需内容的节点SimpleBaseTypeSyntax
。事实上,如果我使用syntax explorer,我会得到:
节点IdentifierToken
拥有我需要的一切,有它的文本
,值
和值文本
属性是“MyBaseClass”
但是,虽然在语法资源管理器中可以看到所有这些值,但无法通过编程方式访问它们
因此,我尝试以编程方式检索节点:
IdentifierNameSyntax identifierNode =
simpleBaseType.ChildNodes().OfType<IdentifierNameSyntax>().First();
SyntaxToken identifier = simpleBaseType.Identifier;
string name = identifier.Text;
这会引发异常,因为
symbolInfo。Symbol
为null
我可以看到您正在尝试使用Roslyn API构建分析器。
您知道还有其他方法来测试您的分析器逻辑吗?使用单元测试文件,而不是直接将源代码放在分析器中
使用这个想法,您可以完全使用VisualStudio提供的模板构建分析器,在该模板中,您必须继承DiagnosticanAnalyzer并创建分析代码逻辑
对于您的情况,您应该查看ClassDeclaration并轻松访问节点内的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";
}
实际上,我不知道为什么不能通过
GetSymbolInfo()
将BaseTypeSyntax
传递给语义模型,但它也会返回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;
var-tree=CSharpSyntaxTree.ParseText(@)
使用制度;
类MyBaseClass
{
}
类MyClass:MyBaseClass{
静态void Main(字符串[]参数){
Console.WriteLine(“你好,世界!”);
}
}");
var Mscorlib=PortableExecutableReference.CreateFromAssembly(typeof(object.Assembly));
var compilation=csharpcomilation.Create(“MyCompilation”,
syntaxTrees:new[]{tree},references:new[]{Mscorlib});
var model=compilation.GetSemanticModel(树);
var myClass=tree.GetRoot().degenantNodes().OfType().Last();
var myClassSymbol=model.GetDeclaredSymbol(myClass);
var baseTypeName=myClassSymbol.BaseType.Name;
您需要在此处使用语义模型,因为您无法可靠地判断您是在语法级别处理接口还是基类。这是我的帮助器类,它可以查找所有属性、类名、类命名空间和基类
protected static bool IsWebPage(SyntaxNodeAnalysisContext context, ClassDeclarationSyntax classDeclaration)
{
INamedTypeSymbol iSymbol = context.SemanticModel.GetDeclaredSymbol(classDeclaration) as INamedTypeSymbol;
INamedTypeSymbol symbolBaseType = iSymbol?.BaseType;
while (symbolBaseType != null)
{
if (symbolBaseType.ToString() == "System.Web.UI.Page")
return true;
symbolBaseType = symbolBaseType.BaseType;
}
return false;
}
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MyProject
{
public class CsharpClass
{
public string Name { get; set; }
public string Namespace { get; set; }
public List<CsharpProperty> Properties { get; set; }
public List<string> BaseClasses { get; set; }
public class CsharpProperty
{
public string Name { get; set; }
public string Type { get; set; }
public CsharpProperty(string name, string type)
{
Name = name;
Type = type;
}
}
public CsharpClass()
{
Properties = new List<CsharpProperty>();
BaseClasses = new List<string>();
}
}
public static class CsharpClassParser
{
public static CsharpClass Parse(string content)
{
var csharpClass = new CsharpClass();
var tree = CSharpSyntaxTree.ParseText(content);
var members = tree.GetRoot().DescendantNodes().OfType<MemberDeclarationSyntax>();
foreach (var member in members)
{
if (member is PropertyDeclarationSyntax property)
{
csharpClass.Properties.Add(new CsharpClass.CsharpProperty(
property.Identifier.ValueText, property.Type.ToString()));
}
if (member is NamespaceDeclarationSyntax namespaceDeclaration)
{
csharpClass.Namespace = namespaceDeclaration.Name.ToString();
}
if (member is ClassDeclarationSyntax classDeclaration)
{
csharpClass.Name = classDeclaration.Identifier.ValueText;
csharpClass.BaseClasses = GetBaseClasses(classDeclaration).ToList();
}
//if (member is MethodDeclarationSyntax method)
//{
// Console.WriteLine("Method: " + method.Identifier.ValueText);
//}
}
return csharpClass;
}
private static IEnumerable<string> GetBaseClasses(ClassDeclarationSyntax classDeclaration)
{
if (classDeclaration == null)
{
return null;
}
if (classDeclaration.BaseList == null)
{
return null;
}
return classDeclaration.BaseList.Types.Select(x => x.Type.ToString());
}
}
}
首先,您可能需要语义模型。如果对创建的编译对象调用GetDiagnostics(),是否存在任何错误?如果设置错误,您可能无法获得任何绑定信息;你知道怎么弄到这个吗?
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
namespace MyProject
{
public class CsharpClass
{
public string Name { get; set; }
public string Namespace { get; set; }
public List<CsharpProperty> Properties { get; set; }
public List<string> BaseClasses { get; set; }
public class CsharpProperty
{
public string Name { get; set; }
public string Type { get; set; }
public CsharpProperty(string name, string type)
{
Name = name;
Type = type;
}
}
public CsharpClass()
{
Properties = new List<CsharpProperty>();
BaseClasses = new List<string>();
}
}
public static class CsharpClassParser
{
public static CsharpClass Parse(string content)
{
var csharpClass = new CsharpClass();
var tree = CSharpSyntaxTree.ParseText(content);
var members = tree.GetRoot().DescendantNodes().OfType<MemberDeclarationSyntax>();
foreach (var member in members)
{
if (member is PropertyDeclarationSyntax property)
{
csharpClass.Properties.Add(new CsharpClass.CsharpProperty(
property.Identifier.ValueText, property.Type.ToString()));
}
if (member is NamespaceDeclarationSyntax namespaceDeclaration)
{
csharpClass.Namespace = namespaceDeclaration.Name.ToString();
}
if (member is ClassDeclarationSyntax classDeclaration)
{
csharpClass.Name = classDeclaration.Identifier.ValueText;
csharpClass.BaseClasses = GetBaseClasses(classDeclaration).ToList();
}
//if (member is MethodDeclarationSyntax method)
//{
// Console.WriteLine("Method: " + method.Identifier.ValueText);
//}
}
return csharpClass;
}
private static IEnumerable<string> GetBaseClasses(ClassDeclarationSyntax classDeclaration)
{
if (classDeclaration == null)
{
return null;
}
if (classDeclaration.BaseList == null)
{
return null;
}
return classDeclaration.BaseList.Types.Select(x => x.Type.ToString());
}
}
}
const string content = @"
namespace Acme.Airlines.AirCraft
{
public class AirCraft
{
public virtual string Name { get; set; }
public virtual int Code { get; set; }
public AirCraft()
{
}
}
}";
var csharpClass = CsharpClassParser.Parse(content);
Console.WriteLine(csharpClass.Name);
Console.WriteLine(csharpClass.Namespace);
Console.WriteLine(csharpClass.Properties.Count);
Console.WriteLine(csharpClass.BaseClasses.Count);