【问题标题】:Roslyn Analyzer Object initializerRoslyn Analyzer 对象初始化器
【发布时间】:2018-03-21 12:53:23
【问题描述】:

我想让分析器检测所有对 setter 属性的调用,而不是在实现特定接口的对象的对象初始化程序中。我有点不知道如何检测到这一点,文档有点薄。我可以得到一个调用表达式,但是如何检查它是否在对象初始化器中?

有什么想法吗?

【问题讨论】:

  • 使用语法可视化工具查看语法树的样子。

标签: roslyn roslyn-code-analysis


【解决方案1】:

要知道对象初始化器中是否有任何特定代码,您可以简单地查找类型为 InitializerExpressionSyntax 的任何节点的祖先。

var initializer = node.Ancestors().OfType<InitializerExpressionSyntax>.FirstOrDefault();

要知道任何特定代码是否是对属性设置器的赋值,您需要做更多的工作。您需要向SemanticModel 询问分配给AssignmentExpressionSyntax 的符号。您的分析器应该可以从其参数/上下文中访问正确的 SemanticModelSyntaxTree

SemanticModel model = ...;
AssignmentExpressionSyntax assignment = ...; // find the assignment
var symbol = model.GetSymbolInfo(assignment).Symbol as IMethodSymbol;
if (symbol?.MethodKind == MethodKind.PropertySet) { ... }

要知道对象是否实现了特定接口,您需要找到对象的符号。您可以通过查找属性设置器符号的包含符号链来找到它。您还可以通过查找应该是您已有的InitializerExpressionSyntax 的父级或祖先的ObjectCreationExpressionSyntax 来找到该对象的符号。

一旦你有了那个创建节点,你就可以再次询问SemanticModel。使用GetTypeInfo 方法获取表达式的类型(正在构造的类型/符号),而不是构造函数的符号。

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)) { ... }

【讨论】:

    猜你喜欢
    • 2014-06-17
    • 2013-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多