从罗斯林的符号中获取类型

ant*_*ive 8 .net c# reflection roslyn roslyn-code-analysis

对于不同类型的符号,从Microsoft.CodeAnalysis.ISymbol获取System.Type的最佳通用方法是什么?(例如类声明,变量,属性等)

我希望能够对类型进行各种检查,例如检查类型是否实现任何接口,或者是否可以转换为任何接口,就像可以检查System.Type一样.

我遇到的问题是,用于表示符号的大多数具体类都是内部的(请参阅http://source.roslyn.io/),我在ISymbol中找不到tye类型信息.

  • SourceNamedTypeSymbol
  • LocalSymbol

我使用以下代码检索ISymbol

var objectSymbol = (ISymbol)model.GetDeclaredSymbol(obj.Node);
Run Code Online (Sandbox Code Playgroud)

Jer*_*vel 14

简短的回答:你做不到.没有正确的方法System.TypeISymbol(罗斯林)获得(反射).

在你想要的方向上做的一个选择是构建你的类型的完全限定名称,然后通过反射查看(例子).

你可能应该问问自己,这是否是你需要做的事情 - 反思和罗斯林并不是真的想要一起工作.

但是,您感兴趣的内容也可以通过Roslyn完成.这里的关键是使用语义模型,它具有所有这些信息.所有声明(与使用相对)都有一个特定的过载,允许您获取声明符号并以适当的类型返回它(例如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));
Run Code Online (Sandbox Code Playgroud)

这将显示该类实现的所有接口.但请记住,这仅仅是指当前的定义 - 如果您对基类型感兴趣,则必须自己完成层次结构.

在您的场景中,您应该能够将其强制转换为正确的类型(假设您正在检查声明节点):

var objectSymbol = (INamedTypeSymbol) model.GetDeclaredSymbol(obj.Node);
Run Code Online (Sandbox Code Playgroud)

  • 并强调为什么没有简单的方法:完全有可能你实际上不能得到一个.获得System.Type的唯一方法是使反射加载有问题的程序集,但实际上您可能实际上没有可加载的程序集.从根本上说,Reflection是一个运行时API,运行时和编译时是不同的东西.你最好总是使用Roslyn API,正如Jeroen的精彩回答所描述的那样. (7认同)