使用 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条件分别在 set
和 get
访问器中实现。
我需要在这里找到标识符的“成员类型”的具体原因是为了优化实现post条件。请注意,在上面的 post 编译示例中,本应 returned 的值存储在局部变量中,经过检查,然后对局部变量进行 returned。此存储对于转换评估方法或复杂表达式的 return
语句是必需的,但如果 returned 表达式只是一个字段或局部变量引用,则创建临时存储 local 是一种浪费。
所以,当return
语句被扫描时,我首先检查语句是否是ReturnKeyword
-IdentifierSyntaxToken
-SemicolonToken
的形式。如果是这样,那么我需要检查该标识符所指的是什么,因此如果所指对象是字段或 var,我将避免局部变量分配。
更新
有关更多上下文,请查看在 GitHub.
上引用的项目
您需要使用 SemanticModel.GetSymbolInfo
来确定标识符绑定的符号。
使用SemanticModel.GetTypeInfo.Type
获取TypeInfo并用它来探索Type
我正在尝试使用 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条件分别在 set
和 get
访问器中实现。
我需要在这里找到标识符的“成员类型”的具体原因是为了优化实现post条件。请注意,在上面的 post 编译示例中,本应 returned 的值存储在局部变量中,经过检查,然后对局部变量进行 returned。此存储对于转换评估方法或复杂表达式的 return
语句是必需的,但如果 returned 表达式只是一个字段或局部变量引用,则创建临时存储 local 是一种浪费。
所以,当return
语句被扫描时,我首先检查语句是否是ReturnKeyword
-IdentifierSyntaxToken
-SemicolonToken
的形式。如果是这样,那么我需要检查该标识符所指的是什么,因此如果所指对象是字段或 var,我将避免局部变量分配。
更新 有关更多上下文,请查看在 GitHub.
上引用的项目您需要使用 SemanticModel.GetSymbolInfo
来确定标识符绑定的符号。
使用SemanticModel.GetTypeInfo.Type
获取TypeInfo并用它来探索Type