[英]Get type from property with Roslyn
使用 Roslyn 我试图解释一些看起来像这样的代码:
public class Foo
{
public override Type BarType
{
get { return typeof(MyBar); }
}
}
我想做的是获取MyBar
然后将该类型作为符号获取,但我不确定这是否可行或可行。 我将有几个看起来像这样的类,它们都派生自一个基类。
鉴于Foo
的ClassDeclarationSyntax
,我可以这样做:
var prop = syntax.DescendantNodes().OfType<PropertyDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ToString() == "BarType");
或者给定Foo
的INamedTypeSymbol
,我可以这样做:
var member = symbol.GetMembers("BarType").FirstOrDefault();
但我不知道从那里去哪里。
最终,我希望能够获得MyBar
的符号以进行进一步分析,因此即使获得字符串"MyBar"
也无济于事,因为它不完全合格。
有什么建议么?
编辑:
我得到一个项目和这样的汇编:
var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(projectPath).Result;
var compilation = project.GetCompilationAsync().Result;
compilation
是这里的CSharpCompilation
。 从那里我做这样的事情:
foreach (var doc in project.Documents)
{
Console.WriteLine($"Analyzing {doc.Name}");
//var model = doc.GetSemanticModelAsync().Result;
var tree = doc.GetSyntaxTreeAsync().Result;
var root = tree.GetRoot();
var model = compilation.GetSemanticModel(tree);
var classes = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach (var syntax in classes)
{
var symbol = model.GetDeclaredSymbol(syntax);
//... need to analyze properties in the class here...
}
}
无论哪种方式,我得到的model
我结束了一个SyntaxTreeSemanticModel
这似乎不具有GetTypeSymbol
方法。
您需要语义模型,它来自Compilation
(带有参考和配置)。
然后,您可以在该节点上调用
GetTypeSymbol()
GetSymbolInfo()
并转换为INamedTypeSymbol
。
您应该寻找ReturnStatementSyntax
和TypeOfExpressionSyntax
。 这包含类型MyBar
。 使用SemanticModel
您可以像这样获得SymbolInfo
:
var classDeclarationSyntaxs = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach ( var classDeclarationSyntax in classDeclarationSyntaxs )
{
var propertyDeclarationSyntaxs = classDeclarationSyntax.Members.OfType<PropertyDeclarationSyntax>();
var barTypePropertyDeclarationSyntax = propertyDeclarationSyntaxs.FirstOrDefault( p => p.Identifier.Text == "BarType" );
if ( barTypePropertyDeclarationSyntax != null )
{
var returnStatementSyntax = barTypePropertyDeclarationSyntax.DescendantNodes().OfType<ReturnStatementSyntax>().FirstOrDefault();
if ( returnStatementSyntax != null )
{
var typeOfExpressionSyntax = returnStatementSyntax.ChildNodes().OfType<TypeOfExpressionSyntax>().FirstOrDefault();
if ( typeOfExpressionSyntax != null )
{
var symbolInfo = semanticModel.GetSymbolInfo( typeOfExpressionSyntax.Type );
var symbolInfoSymbol = symbolInfo.Symbol;
}
}
}
}
您还可以为此使用SyntaxWalker
:
public class TypeOfSyntaxWalker : CSharpSyntaxWalker
{
private readonly SemanticModel _semanticModel;
public ISymbol SymbolInfoSymbol { get; private set; }
public TypeOfSyntaxWalker( SemanticModel semanticModel )
{
_semanticModel = semanticModel;
}
public override void VisitTypeOfExpression( TypeOfExpressionSyntax typeOfExpressionSyntax )
{
var parent = typeOfExpressionSyntax.Parent;
if ( parent.Kind() == SyntaxKind.ReturnStatement )
{
var propertyDeclarationSyntax = parent.FirstAncestorOrSelf<PropertyDeclarationSyntax>();
if ( propertyDeclarationSyntax != null &&
propertyDeclarationSyntax.Identifier.ValueText == "BarType" )
{
var symbolInfo = _semanticModel.GetSymbolInfo( typeOfExpressionSyntax.Type );
SymbolInfoSymbol = symbolInfo.Symbol;
}
}
base.VisitTypeOfExpression( typeOfExpressionSyntax );
}
}
用法:
var classDeclarationSyntaxs = root.DescendantNodes().OfType<ClassDeclarationSyntax>();
foreach ( var classDeclarationSyntax in classDeclarationSyntaxs )
{
var typeOfSyntaxWalker = new TypeOfSyntaxWalker( semanticModel );
typeOfSyntaxWalker.VisitClassDeclaration( classDeclarationSyntax );
var symbolInfoSymbol = typeOfSyntaxWalker.SymbolInfoSymbol;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.