如何将 Roslyn 用于网站项目?

How do I use Roslyn with a Website project?

在我的 Visual Studio 包中,我得到了 Josh Varty 描述的 VisualStudioWorkspace https://joshvarty.com/2014/09/12/learn-roslyn-now-part-6-working-with-workspaces/

使用 EnvDTE.Project 对象,我通过比较属性 CodeAnalysis.Project.FilePath 和 EnvDTE.Project.FileName.

在 VisualStudioWorkspace.Projects 中寻找匹配的 Roslyn 项目

如果找到匹配项,则我知道该项目支持 Roslyn,并且我可以在 CodeAnalysis.Project.Documents 集合中找到文档。到目前为止,这对 C# 和 VB 项目来说效果很好。

如果我没有找到匹配项,那么它可能是一个不支持 Roslyn 的 C++ 项目。

但是,我现在发现 WebSite 项目的行为完全不同。

我在Visual Studio2019新建了一个WebSite项目,虽然解决方案只包含一个项目,但VisualStudioWorkspace包含两个CodeAnalysis.Project对象,如下:

?VSWorkspace.CurrentSolution.Projects(0)
1_Default.aspx
    AdditionalDocumentIds: Count = 0
    AdditionalDocuments: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.TextDocument)}
    AllProjectReferences: Length = 1
    AnalyzerConfigDocuments: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of System.Collections.Generic.KeyValuePair(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.AnalyzerConfigDocumentState), Microsoft.CodeAnalysis.AnalyzerConfigDocument)}
    AnalyzerOptions: {Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions}
    AnalyzerReferences: Length = 0
    AssemblyName: "1_Default"
    CompilationOptions: {Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions}
    DefaultNamespace: ""
    DocumentIds: Count = 2
    Documents: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.Document)}
    FilePath: Nothing
    HasDocuments: True
    Id: (ProjectId, #ca6b1f58-967a-4c31-a874-71d7720dd972 - 1_Default.aspx)
    IsSubmission: False
    Language: "C#"
    LanguageServices: {Microsoft.CodeAnalysis.Host.Mef.MefLanguageServices}
    MetadataReferences: Length = 56
    Name: "1_Default.aspx"
    OutputFilePath: Nothing
    OutputRefFilePath: Nothing
    ParseOptions: {Microsoft.CodeAnalysis.CSharp.CSharpParseOptions}
    ProjectReferences: {System.Linq.Enumerable.WhereEnumerableIterator(Of Microsoft.CodeAnalysis.ProjectReference)}
    Solution: {Microsoft.CodeAnalysis.Solution}
    SupportsCompilation: True
    Version: {2019-10-13T06:46:42.2691386Z-10141-0}
?VSWorkspace.CurrentSolution.Projects(1)
2_App_Code
    AdditionalDocumentIds: Count = 0
    AdditionalDocuments: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.TextDocument)}
    AllProjectReferences: Length = 0
    AnalyzerConfigDocuments: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of System.Collections.Generic.KeyValuePair(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.AnalyzerConfigDocumentState), Microsoft.CodeAnalysis.AnalyzerConfigDocument)}
    AnalyzerOptions: {Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions}
    AnalyzerReferences: Length = 0
    AssemblyName: "App_Code.yy7qumxk"
    CompilationOptions: {Microsoft.CodeAnalysis.CSharp.CSharpCompilationOptions}
    DefaultNamespace: ""
    DocumentIds: Count = 5
    Documents: {System.Linq.Enumerable.WhereSelectEnumerableIterator(Of Microsoft.CodeAnalysis.DocumentId, Microsoft.CodeAnalysis.Document)}
    FilePath: Nothing
    HasDocuments: True
    Id: (ProjectId, #12ab68ac-7b29-4252-87c2-67dc2f3d0696 - 2_App_Code)
    IsSubmission: False
    Language: "C#"
    LanguageServices: {Microsoft.CodeAnalysis.Host.Mef.MefLanguageServices}
    MetadataReferences: Length = 53
    Name: "2_App_Code"
    OutputFilePath: Nothing
    OutputRefFilePath: Nothing
    ParseOptions: {Microsoft.CodeAnalysis.CSharp.CSharpParseOptions}
    ProjectReferences: {System.Linq.Enumerable.WhereEnumerableIterator(Of Microsoft.CodeAnalysis.ProjectReference)}
    Solution: {Microsoft.CodeAnalysis.Solution}
    SupportsCompilation: True
    Version: {2019-10-13T06:46:41.6118955Z-10139-2}

首先,两个项目的文件路径属性都是空的,所以我无法通过文件名来识别项目。

两个项目一共包含了七个文件,分别是:

"C:\DotNetTestPrograms19\CS\WebSite1\Default.aspx.cs"
"C:\DotNetTestPrograms19\CS\WebSite1\Default.aspx"

"C:\DotNetTestPrograms19\CS\WebSite1\App_Code\BundleConfig.cs"
"C:\DotNetTestPrograms19\CS\WebSite1\App_Code\IdentityModels.cs"
"C:\DotNetTestPrograms19\CS\WebSite1\App_Code\RouteConfig.cs"
"C:\DotNetTestPrograms19\CS\WebSite1\App_Code\Startup.Auth.cs"
"C:\DotNetTestPrograms19\CS\WebSite1\App_Code\Startup.cs"

这不是项目中文档的完整列表。该项目包含七个附加代码隐藏文件:

Account\Login.apsx.cs
Account\Manage.apsx.cs
Account\OpenAuthProviders.ascx.cs
Account\Register.apsx.cs
Account\RegisterExternalLogin.apsx.cs
Site.master.cs
ViewSwitcher.ascx.cs

我的问题是,我可以在 WebSite 项目中使用 Roslyn 吗?

显然,EnvDTE 和 CodeAnalysis 项目之间没有一对一的关系。我想我可以解决这个问题。

但是丢失的文件呢?没有七个额外的代码隐藏文件的 Roslyn 文档吗?

终于又看了一遍这个问题,找到了下面的解决方法。

此方法仅在文档在 Visual Studio 中打开时有效。因此我从

开始
projectItem.Open ( EnvDTE.Constants.vsViewKindTextView ) ;

(我的函数中已经有了项目项,所以这很简单。)

然后,有了文件的完整路径 (FullPath) 和 VisualStudioWorkspace (VSWorkspace),我可以使用

获取 Roslyn 文档
var docid = VSWorkspace.CurrentSolution.GetDocumentIdsWithFilePath(FullPath).FirstOrDefault() ;
if ( docid != null )
{
  var RoslynDoc = VSWorkspace.CurrentSolution.GetDocument ( docid ) ;
}

如果文档尚未打开,最好在完成后再次关闭它。您可以确定文档之前是否使用

打开
var wasOpen = projectItem.IsOpen ( EnvDTE.Constants.vsViewKindTextView ) ;

顺便说一句,像这样打开文档不会使 window 在 Visual Studio 中可见(这在我的应用程序中很好)。如果你想让它可见,你可以这样打开它:

var wnd = projectItem.Open ( EnvDTE.Constants.vsViewKindTextView ) ;
wnd.Visible = true ;