使用 Roslyn,如果我有一个 IdentifierNameSyntax,我能否找到它所指的成员类型(字段,属性,方法...)

Using Roslyn, if I have an IdentifierNameSyntax, can I find the member type it refers to (field, property, method...)

我正在尝试使用 Roslyn SDK 和 StackExchange.Precompilation(谢谢!)在 C#6 中实现面向方面的编程。我现在的具体问题是,从一个 IdentifierNameSyntax 实例开始,我想找到标识符所指的“成员类型”(方法、属性、字段、var 等)。 (如何)可以做到这一点?


背景:

我正在进行的第一个概念验证是一些很好的旧合同设计。我有一个 NonNullAttribute 可以应用于参数、属性或方法 return 值。除了属性之外,还有一个 class 实现 StackExchange.Precompilation.ICompileModule 接口,在编译时会在标记的参数或 return 值上插入空检查。

这与 PostSharp 的 NonNullAttribute 想法相同,但转换是在 Roslyn 的语法树之一上完成的,而不是在已编译的程序集上完成的。它也类似于 Code Contracts,但使用声明属性方法,并且再次在非 IL 的语法树上运行。

比如这个源码:

[return: NonNull]
public string Capitalize([NonNull] string text) {
    return text.ToUpper();
}

预编译时会变成这样:

[return: NonNull]
public string Capitalize([NonNull] string text) {
    if (Object.Equals(text, null)) 
        throw new ArgumentNullException(nameof(text));

    var result = text.ToUpper();
    if (Object.Equals(result, null))
        throw new PostconditionFailedException("Result cannot be null.");
    return result;
}

PostconditionFailedException 是我为 return 值称赞 ArgumentException 的自定义异常。如果框架中已经有类似的东西,请告诉我。)

对于具有此属性的属性,会有类似的转换,但前提条件和 post条件分别在 setget 访问器中实现。


我需要在这里找到标识符的“成员类型”的具体原因是为了优化实现post条件。请注意,在上面的 post 编译示例中,本应 returned 的值存储在局部变量中,经过检查,然后对局部变量进行 returned。此存储对于转换评估方法或复杂表达式的 return 语句是必需的,但如果 returned 表达式只是一个字段或局部变量引用,则创建临时存储 local 是一种浪费。

所以,当return语句被扫描时,我首先检查语句是否是ReturnKeyword-IdentifierSyntaxToken-SemicolonToken的形式。如果是这样,那么我需要检查该标识符所指的是什么,因此如果所指对象是字段或 var,我将避免局部变量分配。

更新 有关更多上下文,请查看在 GitHub.

上引用的项目

您需要使用 SemanticModel.GetSymbolInfo 来确定标识符绑定的符号。

使用SemanticModel.GetTypeInfo.Type获取TypeInfo并用它来探索Type