簡體   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