当该方法没有符号信息时,如何使用 Roslyn 获取被调用方法的包含命名空间?
How do I get the containing namespace of a called method using Roslyn when that method has no symbol info?
我有一个允许用户编写 c-sharp 代码的应用程序,这些代码被保存为 class 库供以后调用。
已建立新要求,不再允许使用某些命名空间(及其包含的方法以及具有 return 类型的任何变量或方法)。所以我需要分析代码并提醒用户注意他们代码中的任何禁止命名空间,以便他们可以删除它们。
使用 Roslyn,我可以访问 InvocationExpressionSyntax
节点以进行方法调用。然后我通过调用 var mySymbol = mySemanticModel.GetSymbolInfo(myInvocationExpressionSyntaxNode).Symbol
.
获取符号信息
然后调用 mySymbol.ContainingType.ToDisplayString()
return调用的命名空间类型。
但是,Roslyn 中似乎并不是所有被调用的方法都有符号信息。例如,System.Math.Sqrt()
有符号信息,因此我可以从中得到 System.Math
的包含命名空间。另一方面 System.Net.WebRequest.Create()
或 System.Diagnostics.Process.Start()
则不会。如何从这些节点获取 System.Net.WebRequest
或 System.Dignostics.Process
?我可以使用 QuickWatch 清楚地看到它们。
例如,System.Diagnostics.Process.Start()
节点本身在 QuickWatch 中显示以下值:
InvocationExpressionSyntax InvocationExpression System.Diagnostics.Process.Start("CMD.exe","")
并且节点的表达式具有以下值:
MemberAccessExpressionSyntax SimpleMemberAccessExpression System.Diagnostics.Process.Start
很明显,名称空间存在于值本身中。但是 SymbolInfo 中的 Symbol 和 TypeInfo 中的 Type 都是空的。
编辑
关于我的编译,C# Roslyn 工具设置如下(我们应该也支持 VB,因此属性是接口的):
private class CSharpRoslynTools : IRoslynTools
{
public CompilationUnitSyntax SyntaxTreeRoot { get; }
public SemanticModel SemanticModel { get; }
public CSharpRoslynTools(string code)
{
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create(
"MyCompilation",
syntaxTrees: new[] { syntaxTree },
references: new[]
{
mscorlib
});
this.SemanticModel = compilation.GetSemanticModel(syntaxTree);
this.SyntaxTreeRoot = (CompilationUnitSyntax)syntaxTree.GetRoot();
}
}
我确实意识到的一件事是系统诊断不是 mscorlib 的一部分。这可能是符号信息丢失的原因吗?
老实说,我认为这有点浪费我的时间,因为这些脚本被设计为 运行 在 WinForms 桌面应用程序中,此时可能已有 15 年的历史了。但随后他们决定将此桌面应用程序迁移到特定客户的 Citrix Cloud。因此,如果不是管理员登录到应用程序,我们必须锁定任何可以访问文件系统的东西。因此,这些脚本存在巨大的潜在安全漏洞。不过,有人访问该应用程序并利用其中任何一个的机会很小。
我推动了一个黑名单,这很容易通过简单的代码字符串搜索来完成。他们想要一个需要完全解析符号的白名单。
However, it seems not all called methods have symbol information in Roslyn.
这可能表明您获取合集的方式出了问题,您应该尝试直接调查。不要试图在下游处理它。 (软件:输入垃圾,输出垃圾!)
On the other hand System.Net.WebRequest.Create() or System.Diagnostics.Process.Start() do not. How do I get System.Net.WebRequest or System.Dignostics.Process from those nodes? I can clearly see them using QuickWatch.
请记住,从 仅语法 的角度来看,System.Net.WebRequest.Create() 可能是:
- System.Net
中 WebRequest 类型的 Create 方法
- WebRequest 类型上的 Create 方法,它是 System 命名空间中嵌套的 class Net 类型
- MyApp.System.Net.WebRequest 中 WebRequest 类型的 Create 方法,因为我们当然不需要完整的命名空间名称,如果您决定在 MyApp 中创建一个系统命名空间,那可以可能有用!
One thing I did come to realize is that System Diagnostics isn't part of the mscorlib. Could that be why the symbol information is missing?
是的;我们只会引用您提供给我们的程序集。您需要了解您的上下文,如果该代码可以引用的内容中包含其他引用,那么您应该将它们包含在您的编译作品中。
I pushed for a blacklist, which would be easy enough to do with a simple string search of the code. They want a whitelist which requires full out parsing of the symbols.
从安全角度来看,他们可能是对的——很难阻止字符串搜索。请参阅 中的一些想法,了解这有多困难。
我有一个允许用户编写 c-sharp 代码的应用程序,这些代码被保存为 class 库供以后调用。
已建立新要求,不再允许使用某些命名空间(及其包含的方法以及具有 return 类型的任何变量或方法)。所以我需要分析代码并提醒用户注意他们代码中的任何禁止命名空间,以便他们可以删除它们。
使用 Roslyn,我可以访问 InvocationExpressionSyntax
节点以进行方法调用。然后我通过调用 var mySymbol = mySemanticModel.GetSymbolInfo(myInvocationExpressionSyntaxNode).Symbol
.
然后调用 mySymbol.ContainingType.ToDisplayString()
return调用的命名空间类型。
但是,Roslyn 中似乎并不是所有被调用的方法都有符号信息。例如,System.Math.Sqrt()
有符号信息,因此我可以从中得到 System.Math
的包含命名空间。另一方面 System.Net.WebRequest.Create()
或 System.Diagnostics.Process.Start()
则不会。如何从这些节点获取 System.Net.WebRequest
或 System.Dignostics.Process
?我可以使用 QuickWatch 清楚地看到它们。
例如,System.Diagnostics.Process.Start()
节点本身在 QuickWatch 中显示以下值:
InvocationExpressionSyntax InvocationExpression System.Diagnostics.Process.Start("CMD.exe","")
并且节点的表达式具有以下值:
MemberAccessExpressionSyntax SimpleMemberAccessExpression System.Diagnostics.Process.Start
很明显,名称空间存在于值本身中。但是 SymbolInfo 中的 Symbol 和 TypeInfo 中的 Type 都是空的。
编辑
关于我的编译,C# Roslyn 工具设置如下(我们应该也支持 VB,因此属性是接口的):
private class CSharpRoslynTools : IRoslynTools
{
public CompilationUnitSyntax SyntaxTreeRoot { get; }
public SemanticModel SemanticModel { get; }
public CSharpRoslynTools(string code)
{
var mscorlib = MetadataReference.CreateFromFile(typeof(object).Assembly.Location);
var syntaxTree = CSharpSyntaxTree.ParseText(code);
var compilation = CSharpCompilation.Create(
"MyCompilation",
syntaxTrees: new[] { syntaxTree },
references: new[]
{
mscorlib
});
this.SemanticModel = compilation.GetSemanticModel(syntaxTree);
this.SyntaxTreeRoot = (CompilationUnitSyntax)syntaxTree.GetRoot();
}
}
我确实意识到的一件事是系统诊断不是 mscorlib 的一部分。这可能是符号信息丢失的原因吗?
老实说,我认为这有点浪费我的时间,因为这些脚本被设计为 运行 在 WinForms 桌面应用程序中,此时可能已有 15 年的历史了。但随后他们决定将此桌面应用程序迁移到特定客户的 Citrix Cloud。因此,如果不是管理员登录到应用程序,我们必须锁定任何可以访问文件系统的东西。因此,这些脚本存在巨大的潜在安全漏洞。不过,有人访问该应用程序并利用其中任何一个的机会很小。
我推动了一个黑名单,这很容易通过简单的代码字符串搜索来完成。他们想要一个需要完全解析符号的白名单。
However, it seems not all called methods have symbol information in Roslyn.
这可能表明您获取合集的方式出了问题,您应该尝试直接调查。不要试图在下游处理它。 (软件:输入垃圾,输出垃圾!)
On the other hand System.Net.WebRequest.Create() or System.Diagnostics.Process.Start() do not. How do I get System.Net.WebRequest or System.Dignostics.Process from those nodes? I can clearly see them using QuickWatch.
请记住,从 仅语法 的角度来看,System.Net.WebRequest.Create() 可能是:
- System.Net 中 WebRequest 类型的 Create 方法
- WebRequest 类型上的 Create 方法,它是 System 命名空间中嵌套的 class Net 类型
- MyApp.System.Net.WebRequest 中 WebRequest 类型的 Create 方法,因为我们当然不需要完整的命名空间名称,如果您决定在 MyApp 中创建一个系统命名空间,那可以可能有用!
One thing I did come to realize is that System Diagnostics isn't part of the mscorlib. Could that be why the symbol information is missing?
是的;我们只会引用您提供给我们的程序集。您需要了解您的上下文,如果该代码可以引用的内容中包含其他引用,那么您应该将它们包含在您的编译作品中。
I pushed for a blacklist, which would be easy enough to do with a simple string search of the code. They want a whitelist which requires full out parsing of the symbols.
从安全角度来看,他们可能是对的——很难阻止字符串搜索。请参阅 中的一些想法,了解这有多困难。