[英]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.