如何将 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 ;
在我的 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 ;