从 roslyn 中的符号获取类型
Getting type from a symbol in roslyn
对于不同类型的符号,从 Microsoft.CodeAnalysis.ISymbol 获得 System.Type 的最佳通用方法是什么? (例如 class 声明、变量、属性等)
我希望能够对类型进行各种检查,例如作为检查类型是否实现任何接口或是否可转换为任何接口,就像可以检查 System.Type.
我遇到的问题是大多数用于表示符号的具体 classes 都是内部的(参见 http://sourceroslyn.io/),我在 ISymbol 中找不到类型信息。
- SourceNamedTypeSymbol
- 本地符号
我使用以下代码检索 ISymbol
var objectSymbol = (ISymbol)model.GetDeclaredSymbol(obj.Node);
简答:你不能。没有正确的方法从 ISymbol
(Roslyn) 获得 System.Type
(反射)。
朝着您想要的方向前进的一个选择是构建您的类型的 fully-qualified 名称,然后通过反射查找它 (example)。
不过,您可能首先应该问问自己,这是否是您需要做的事情——反射和 Roslyn 并不是真的打算一起工作。
不过,您感兴趣的内容也可以通过 Roslyn 完成。这里的关键是使用为您提供所有这些信息的语义模型。
所有声明(与用法相反)都有一个特定的重载可用,它允许您获取声明符号并 return 它以适当的类型(例如本例中的 INamedTypeSymbol
)。
举个例子:
const string source = @"
using System;
namespace MyNamespace
{
class MyClass : IDisposable
{
void Method()
{
MyClass nameOfVariable, another;
}
}
}
";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CSharpCompilation.Create("MyCompilation", new[] { tree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
var semanticModel = compilation.GetSemanticModel(tree);
var root = tree.GetRoot();
var classSymbol = semanticModel.GetDeclaredSymbol(root.DescendantNodes().OfType<ClassDeclarationSyntax>().First());
Console.WriteLine(string.Join(", ", classSymbol.AllInterfaces));
这将显示 class 实现的所有接口。但是请记住,这只是指当前定义——如果您还对基本类型感兴趣,则必须自己查看层次结构。
在您的场景中,您应该能够将其转换为正确的类型(假设您正在检查声明节点):
var objectSymbol = (INamedTypeSymbol) model.GetDeclaredSymbol(obj.Node);
我想这就是你要找的:
var castedProperty = (IPropertySymbol) property;
var type = castedProperty.Type.Name;
变量'property'是一个ISymbol实例。
对于不同类型的符号,从 Microsoft.CodeAnalysis.ISymbol 获得 System.Type 的最佳通用方法是什么? (例如 class 声明、变量、属性等)
我希望能够对类型进行各种检查,例如作为检查类型是否实现任何接口或是否可转换为任何接口,就像可以检查 System.Type.
我遇到的问题是大多数用于表示符号的具体 classes 都是内部的(参见 http://sourceroslyn.io/),我在 ISymbol 中找不到类型信息。
- SourceNamedTypeSymbol
- 本地符号
我使用以下代码检索 ISymbol
var objectSymbol = (ISymbol)model.GetDeclaredSymbol(obj.Node);
简答:你不能。没有正确的方法从 ISymbol
(Roslyn) 获得 System.Type
(反射)。
朝着您想要的方向前进的一个选择是构建您的类型的 fully-qualified 名称,然后通过反射查找它 (example)。
不过,您可能首先应该问问自己,这是否是您需要做的事情——反射和 Roslyn 并不是真的打算一起工作。
不过,您感兴趣的内容也可以通过 Roslyn 完成。这里的关键是使用为您提供所有这些信息的语义模型。
所有声明(与用法相反)都有一个特定的重载可用,它允许您获取声明符号并 return 它以适当的类型(例如本例中的 INamedTypeSymbol
)。
举个例子:
const string source = @"
using System;
namespace MyNamespace
{
class MyClass : IDisposable
{
void Method()
{
MyClass nameOfVariable, another;
}
}
}
";
var tree = CSharpSyntaxTree.ParseText(source);
var compilation = CSharpCompilation.Create("MyCompilation", new[] { tree }, new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) });
var semanticModel = compilation.GetSemanticModel(tree);
var root = tree.GetRoot();
var classSymbol = semanticModel.GetDeclaredSymbol(root.DescendantNodes().OfType<ClassDeclarationSyntax>().First());
Console.WriteLine(string.Join(", ", classSymbol.AllInterfaces));
这将显示 class 实现的所有接口。但是请记住,这只是指当前定义——如果您还对基本类型感兴趣,则必须自己查看层次结构。
在您的场景中,您应该能够将其转换为正确的类型(假设您正在检查声明节点):
var objectSymbol = (INamedTypeSymbol) model.GetDeclaredSymbol(obj.Node);
我想这就是你要找的:
var castedProperty = (IPropertySymbol) property;
var type = castedProperty.Type.Name;
变量'property'是一个ISymbol实例。