Roslyn 分析器对象初始化器
Roslyn Analyzer Object initializer
我想让分析器检测所有对 setter 属性的调用,这些调用不在实现特定接口的对象的对象初始值设定项内。我有点不知道如何检测它,文档有点薄。我可以获得调用表达式,但如何检查它是否在对象初始化器中?
有什么想法吗?
要知道对象初始值设定项中是否有任何特定代码,您只需查找 InitializerExpressionSyntax
.
类型的任何节点的祖先即可
var initializer = node.Ancestors().OfType<InitializerExpressionSyntax>.FirstOrDefault();
要知道是否有任何特定代码是对 属性 setter 的赋值,您需要做更多的工作。您需要向 SemanticModel
询问分配给 AssignmentExpressionSyntax
的符号。您的分析器应该可以从其 arguments/context.
访问正确的 SemanticModel
和 SyntaxTree
SemanticModel model = ...;
AssignmentExpressionSyntax assignment = ...; // find the assignment
var symbol = model.GetSymbolInfo(assignment).Symbol as IMethodSymbol;
if (symbol?.MethodKind == MethodKind.PropertySet) { ... }
要知道该对象是否实现了特定接口,您需要找到该对象的符号。您可以通过查找 属性 setter 符号的包含符号链来找到它。您还可以通过找到应该是您已有的 InitializerExpressionSyntax
的父项或祖先的 ObjectCreationExpressionSyntax
来找到对象的符号。
一旦你有了那个创建节点,你就可以再次询问 SemanticModel
。使用 GetTypeInfo
方法获取表达式的类型(正在构造的 type/symbol)而不是构造函数的符号。
var creation = initializer.Ancestors().OfType<ObjectCreationSyntax>().FirstOrDefault();
var createdType = model.GetTypeInfo(creation).Type as INamedTypeSymbol;
现在,您只需要知道类型是否实现了接口。
首先你需要一个接口类型的符号。获取它的一种快速方法是使用其 CLR 元数据名称进行查找。
var interfaceType = model.Compilation.GetTypeByMetadataName("MyNamspace.MyInterfaceType");
这部分通常在分析器初始化时完成一次,因此您不必一遍又一遍地查找它。
现在您拥有了发现所构造的类型是否实现接口所需的一切。
if (createdType.AllInterfaces.Contains(interfaceType)) { ... }
我想让分析器检测所有对 setter 属性的调用,这些调用不在实现特定接口的对象的对象初始值设定项内。我有点不知道如何检测它,文档有点薄。我可以获得调用表达式,但如何检查它是否在对象初始化器中?
有什么想法吗?
要知道对象初始值设定项中是否有任何特定代码,您只需查找 InitializerExpressionSyntax
.
var initializer = node.Ancestors().OfType<InitializerExpressionSyntax>.FirstOrDefault();
要知道是否有任何特定代码是对 属性 setter 的赋值,您需要做更多的工作。您需要向 SemanticModel
询问分配给 AssignmentExpressionSyntax
的符号。您的分析器应该可以从其 arguments/context.
SemanticModel
和 SyntaxTree
SemanticModel model = ...;
AssignmentExpressionSyntax assignment = ...; // find the assignment
var symbol = model.GetSymbolInfo(assignment).Symbol as IMethodSymbol;
if (symbol?.MethodKind == MethodKind.PropertySet) { ... }
要知道该对象是否实现了特定接口,您需要找到该对象的符号。您可以通过查找 属性 setter 符号的包含符号链来找到它。您还可以通过找到应该是您已有的 InitializerExpressionSyntax
的父项或祖先的 ObjectCreationExpressionSyntax
来找到对象的符号。
一旦你有了那个创建节点,你就可以再次询问 SemanticModel
。使用 GetTypeInfo
方法获取表达式的类型(正在构造的 type/symbol)而不是构造函数的符号。
var creation = initializer.Ancestors().OfType<ObjectCreationSyntax>().FirstOrDefault();
var createdType = model.GetTypeInfo(creation).Type as INamedTypeSymbol;
现在,您只需要知道类型是否实现了接口。
首先你需要一个接口类型的符号。获取它的一种快速方法是使用其 CLR 元数据名称进行查找。
var interfaceType = model.Compilation.GetTypeByMetadataName("MyNamspace.MyInterfaceType");
这部分通常在分析器初始化时完成一次,因此您不必一遍又一遍地查找它。
现在您拥有了发现所构造的类型是否实现接口所需的一切。
if (createdType.AllInterfaces.Contains(interfaceType)) { ... }