我想获取项目中所有使用类型的列表,例如:
var x = 1;
var y = x.ToString().GetType();
代码应返回System.Int32
、System.String
、System.Type
。
我的速度非常慢...对于每个文件(语法树),我执行以下操作:
var root = await syntaxTree.GetRootAsync();
var nodes = root.DescendantNodes(n => true);
if (nodes != null)
{
var syntaxNodes = nodes as SyntaxNode[] ?? nodes.ToArray();
// IdentifierNameSyntax:
// - var keyword
// - identifiers of any kind (including type names)
var namedTypes = syntaxNodes
.OfType<IdentifierNameSyntax>()
.Select(id => this.compilation
.GetSemanticModel(id.SyntaxTree)
.GetSymbolInfo(id)
.Symbol)
.OfType<INamedTypeSymbol>()
.ToArray();
// add the found types to the list
this.AddRange(namedTypes);
// ExpressionSyntax:
// - method calls
// - property uses
// - field uses
// - all kinds of composite expressions
var expressionSyntaxs = syntaxNodes
.OfType<ExpressionSyntax>()
.ToList();
var typeSymbols = new List<ITypeSymbol>();
for (int index = 0; index < expressionSyntaxs.Count; index++)
{
ExpressionSyntax ma = expressionSyntaxs[index];
typeSymbols.Add(this.compilation
.GetSemanticModel(ma.SyntaxTree)
.GetTypeInfo(ma)
.Type);
}
var expressionTypes = typeSymbols
.OfType<INamedTypeSymbol>()
.ToArray();
// add the found types to the list
this.AddRange(expressionTypes);
}
动机:
我正在制作一个分析项目的工具,并告知哪些 .Net 框架版本支持给定项目(例如可移植 .Net 框架)。
我希望在编译之前将一组使用过的类型与框架中的一组可用类型匹配会更快。
对于小文件,此代码足够快,并且总时间少于使用每个可能的框架进行编译的时间......但是对于大文件,这是 Not Acceptable 。
有没有办法以可接受的方式获取类型列表?
最佳答案
因此,我吸取了教训:永远不要假设不可变结构会缓存它的任何计算,只是因为两次调用会返回相同的结果。
的确,当方法是纯方法时,返回在结构上总是相同的,但不一定是相同的实例。
我的假设导致我犯了一个错误:认为 this.compilation.GetSemanticModel(id.SyntaxTree)
总是会为给定的 SyntaxTree
返回相同的语义模型实例>...这不是真的。
我将我的代码更改为以下内容,现在速度非常快:
var root = await syntaxTree.GetRootAsync();
var nodes = root.DescendantNodes(n => true);
var st = root.SyntaxTree;
var sm = this.compilation.GetSemanticModel(st);
if (nodes != null)
{
var syntaxNodes = nodes as SyntaxNode[] ?? nodes.ToArray();
// IdentifierNameSyntax:
// - var keyword
// - identifiers of any kind (including type names)
var namedTypes = syntaxNodes
.OfType<IdentifierNameSyntax>()
.Select(id => sm.GetSymbolInfo(id).Symbol)
.OfType<INamedTypeSymbol>()
.ToArray();
this.Add(namedTypes);
// ExpressionSyntax:
// - method calls
// - property uses
// - field uses
// - all kinds of composite expressions
var expressionTypes = syntaxNodes
.OfType<ExpressionSyntax>()
.Select(ma => sm.GetTypeInfo(ma).Type)
.OfType<INamedTypeSymbol>()
.ToArray();
this.Add(expressionTypes);
}
关于c# - 使用 Roslyn 获取项目中引用类型的列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29176579/