繁体   English   中英

当该方法没有符号信息时,如何使用 Roslyn 获取被调用方法的包含命名空间?

[英]How do I get the containing namespace of a called method using Roslyn when that method has no symbol info?

我有一个应用程序,允许用户编写 c-sharp 代码,该代码被保存为 class 库以供以后调用。

已经建立了一个新要求,即不再允许某些命名空间(以及它们包含的方法以及任何具有返回类型的变量或方法)。 所以我需要分析代码并提醒用户注意他们代码中的任何被禁止的命名空间,以便他们可以删除它们。

使用 Roslyn,我可以访问方法调用的InvocationExpressionSyntax节点。 然后我通过调用var mySymbol = mySemanticModel.GetSymbolInfo(myInvocationExpressionSyntaxNode).Symbol获取符号信息。

然后调用mySymbol.ContainingType.ToDisplayString()返回调用的命名空间类型。

但是,似乎并非所有被调用的方法在 Roslyn 中都有符号信息。 例如, System.Math.Sqrt()具有符号信息,因此我可以从中获取System.Math的包含命名空间。 另一方面System.Net.WebRequest.Create()System.Diagnostics.Process.Start()没有。 如何从这些节点获取System.Net.WebRequestSystem.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 都是 null。

编辑

关于我的编译,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 的一部分。 这可能是缺少符号信息的原因吗?

老实说,我觉得这有点浪费我的时间,因为这些脚本被设计为在一个可能已经有 15 年历史的 WinForms 桌面应用程序中运行。 但后来他们决定将此桌面应用程序迁移到某些客户需要的 Citrix Cloud。 因此,如果不是管理员登录到应用程序,我们必须锁定任何可以访问文件系统的东西。 因此,这些脚本存在巨大的潜在安全漏洞。 但是,有人访问该应用程序并利用其中任何一个的机会很小。

我推动了一个黑名单,这很容易通过简单的代码字符串搜索来完成。 他们想要一个需要完整解析符号的白名单。

但是,似乎并非所有被调用的方法在 Roslyn 中都有符号信息。

这可能表明您获得编译的方式出了问题,您应该尝试直接调查。 不要试图在下游处理它。 (软件:垃圾进,垃圾出!)

另一方面 System.Net.WebRequest.Create() 或 System.Diagnostics.Process.Start() 没有。 如何从这些节点获取 System.Net.WebRequest 或 System.Dignostics.Process? 我可以使用 QuickWatch 清楚地看到它们。

请记住,仅从语法的角度来看, System.Net.WebRequest.Create() 可能是:

  • System.Net 中 WebRequest 类型的 Create 方法
  • WebRequest 类型上的 Create 方法,它是 System 命名空间中 Net 类型的嵌套 class
  • MyApp.System.Net.WebRequest 中的 WebRequest 类型的 Create 方法,因为我们当然不需要完整的命名空间名称,如果您决定在 MyApp 中创建一个 System 命名空间,这可能会起作用!

我确实意识到的一件事是系统诊断不是 mscorlib 的一部分。 这可能是缺少符号信息的原因吗?

是的; 我们只会参考您提供给我们的程序集。 由您来了解您的上下文,如果其他引用包含在该代码可以引用的内容中,那么您应该将它们包含在您的编译生成中。

我推动了一个黑名单,这很容易通过简单的代码字符串搜索来完成。 他们想要一个需要完整解析符号的白名单。

从安全的角度来看,他们可能是对的——很难阻止字符串搜索。 请参阅https://stackoverflow.com/a/66555319/972216上的一些想法,了解这有多困难。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM