[英]Get type from property with Roslyn
Using Roslyn I'm trying to interpret some code that looks something like this:使用 Roslyn 我试图解释一些看起来像这样的代码:
public class Foo
{
public override Type BarType
{
get { return typeof(MyBar); }
}
}
What I would like to do is get MyBar
and then get that type as a symbol, but I'm not sure if this is even something that is possible or practical to do.我想做的是获取
MyBar
然后将该类型作为符号获取,但我不确定这是否可行或可行。 I'm going to have several classes that look like this and all derive from a base class.我将有几个看起来像这样的类,它们都派生自一个基类。
Given the ClassDeclarationSyntax
for Foo
, I can do this:鉴于
Foo
的ClassDeclarationSyntax
,我可以这样做:
var prop = syntax.DescendantNodes().OfType<PropertyDeclarationSyntax>()
.FirstOrDefault(p => p.Identifier.ToString() == "BarType");
Or given the INamedTypeSymbol
for Foo
, I can do this:或者给定
Foo
的INamedTypeSymbol
,我可以这样做:
var member = symbol.GetMembers("BarType").FirstOrDefault();
But I don't know where to go from there.但我不知道从那里去哪里。
Ultimately I want to be able to get the symbol for MyBar
for further analysis, so maybe even getting the string "MyBar"
isn't going to help because it's not fully qualified.最终,我希望能够获得
MyBar
的符号以进行进一步分析,因此即使获得字符串"MyBar"
也无济于事,因为它不完全合格。
Any suggestions?有什么建议么?
EDIT :编辑:
I'm getting a project and a compilation like this:我得到一个项目和这样的汇编:
var workspace = MSBuildWorkspace.Create();
var project = workspace.OpenProjectAsync(projectPath).Result;
var compilation = project.GetCompilationAsync().Result;
compilation
is a CSharpCompilation
here. compilation
是这里的CSharpCompilation
。 From there I do something like this:从那里我做这样的事情:
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...
}
}
Either way I get model
I end up with a SyntaxTreeSemanticModel
which doesn't seem to have a GetTypeSymbol
method.无论哪种方式,我得到的
model
我结束了一个SyntaxTreeSemanticModel
这似乎不具有GetTypeSymbol
方法。
You need the Semantic Model, which comes from a Compilation
(with references & configuration).您需要语义模型,它来自
Compilation
(带有参考和配置)。
You can then call
GetTypeSymbol()
GetSymbolInfo()
on that node and cast to INamedTypeSymbol
.然后,您可以在该节点上调用
GetTypeSymbol()
GetSymbolInfo()
并转换为INamedTypeSymbol
。
You should look for the ReturnStatementSyntax
and TypeOfExpressionSyntax
.您应该寻找
ReturnStatementSyntax
和TypeOfExpressionSyntax
。 This contains the type MyBar
.这包含类型
MyBar
。 With the SemanticModel
you can get the SymbolInfo
like this:使用
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;
}
}
}
}
You can also use a SyntaxWalker
for this:您还可以为此使用
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 );
}
}
Usage:用法:
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.