我正在尝试使用 Roslyn 编译器在 .Net Core 中编写一个类来编译我的项目并返回该项目中的 ClassDefinitions。我将使用该信息通过 T4 生成代码。
这是一个 .Net Core 3.1 项目。
我找不到任何关于应该使用哪些包来完成此任务的良好文档。
在加载解决方案后,在解决方案 getter 中,我在 Documents 属性中没有收到任何文档,并且它尝试加载的每个项目都收到 1 条诊断消息:
System.ApplicationException: 'Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Web\Wur.GroupTool.Web.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Web\Wur.GroupTool.Web.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core\Wur.GroupTool.Core.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core\Wur.GroupTool.Core.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core.Tests\Wur.GroupTool.Core.Tests.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.GroupTool.Core.Tests\Wur.GroupTool.Core.Tests.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata\Wur.Roslyn.Metadata.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata\Wur.Roslyn.Metadata.csproj
Msbuild failed when processing the file 'C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata.Tests\Wur.Roslyn.Metadata.Tests.csproj' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified. C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Roslyn.Metadata.Tests\Wur.Roslyn.Metadata.Tests.csproj
'
我安装了这些软件包(是的,甚至尝试了预发行版):
还必须在“排除 Assets ”属性中设置“运行时”:
这是我的类(class):
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Wur.Roslyn.Metadata
{
public class RoslynProjectProvider
{
public string PathToSolution { get; private set; }
public string ProjectName { get; private set; }
public RoslynProjectProvider(string pathToSolution, string projectName)
{
PathToSolution = pathToSolution;
ProjectName = projectName;
}
private MSBuildWorkspace _Workspace;
public MSBuildWorkspace Workspace
{
get
{
if (_Workspace == null)
{
MSBuildLocator.RegisterDefaults();
_Workspace = MSBuildWorkspace.Create();
}
return _Workspace;
}
}
private Solution _Solution;
public Solution Solution
{
get
{
if (_Solution == null)
{
_Solution = Workspace.OpenSolutionAsync(PathToSolution).Result;
if(Workspace.Diagnostics.Count > 0)
{
StringBuilder sb = new StringBuilder();
foreach (var diagnostic in Workspace.Diagnostics)
{
sb.Append(diagnostic.Message).Append(Environment.NewLine);
}
throw new ApplicationException(sb.ToString());
}
}
return _Solution;
}
}
private Project _Project;
/// <summary>
/// Singleton Project in a solution
/// </summary>
public Project Project
{
get
{
if (_Project == null)
{
_Project = Solution.Projects.FirstOrDefault(p => p.Name.Equals(ProjectName, StringComparison.InvariantCultureIgnoreCase));
if (_Project == null)
{
throw new ApplicationException($"Cannot find project {ProjectName}");
}
}
return _Project;
}
}
private Compilation _Compilation;
/// <summary>
/// Singleton compilation of the project
/// </summary>
public Compilation ProjectCompilation
{
get
{
if (_Compilation == null)
{
_Compilation = Project.GetCompilationAsync().Result;
}
return _Compilation;
}
}
private List<ClassDeclarationSyntax> _Classes;
public List<ClassDeclarationSyntax> Classes
{
get
{
if (_Classes == null)
{
_Classes = new List<ClassDeclarationSyntax>();
foreach (var document in Project.Documents)
{
var tree = document.GetSyntaxTreeAsync().Result;
var semanticModel = ProjectCompilation.GetSemanticModel(tree);
foreach (var type in tree.GetRoot().DescendantNodes().OfType<ClassDeclarationSyntax>())
{
_Classes.Add(type);
}
}
}
return _Classes;
}
}
}
}
还有一个单元测试来测试该类:
public class UnitTest1
{
[Fact]
public void Test1()
{
var provider = new RoslynProjectProvider(@"C:\Projects\FB-IT\grouptool\sources\Wur.Grouptool\Wur.Grouptool.sln", "Wur.GroupTool.Core");
var classes = provider.Classes;
}
}
==编辑==
它要求版本5.0.0.0,但System.Runtime的版本较低。这可能是这里的问题吗?
==编辑==
Remark to first answer: Ok, got it working finally. Had to download the .Net Core 3.1.404 SDK from here: dotnet.microsoft.com/download/dotnet-core/thank-you/…. Added the path as you suggested and voila it started working.
它在单元测试中运行良好,但在 T4 模板中运行不佳。当我尝试运行自定义工具时,出现以下异常(启用绑定(bind)日志记录):
Severity Code Description Project File Line Suppression State
Error Running transformation: System.IO.FileNotFoundException: Could not load file or assembly 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
File name: 'System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at Microsoft.VisualStudio.TextTemplating9A1960153A0EC5389F1AC1A553BA062D21024CF3A0BEA5F9915226007DBBA0457E39D7A79FF10F4293C4331881904FF0454986C06541AC3156F88310BB537850.GeneratedTextTransformation.TransformText()
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at Microsoft.VisualStudio.TextTemplating.TransformationRunner.PerformTransformation()
=== Pre-bind state information ===
LOG: DisplayName = System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
(Fully-specified)
LOG: Appbase = file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/
LOG: Initial PrivatePath = NULL
Calling assembly : Wur.Roslyn.Metadata, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in LoadFrom load context.
WRN: Native image will not be probed in LoadFrom context. Native image will only be probed in default load context, like with Assembly.Load().
LOG: Using application configuration file: C:\Users\User\AppData\Local\Microsoft\VisualStudio\16.0_966a030a\devenv.exe.config
LOG: Using host configuration file:
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework\v4.0.30319\config\machine.config.
LOG: Post-policy reference: System.Runtime, Version=4.2.2.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PublicAssemblies/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Microsoft/TestWindow/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/CommonExtensions/Platform/Debugger/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Program Files (x86)/Microsoft Visual Studio/2019/Professional/Common7/IDE/PrivateAssemblies/DataCollectors/x86/System.Runtime/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime/System.Runtime.DLL.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime.EXE.
LOG: Attempting download of new URL file:///C:/Projects/FB-IT/grouptool/sources/Wur.GroupTool/Wur.Roslyn.Metadata/bin/Debug/netcoreapp3.1/System.Runtime/System.Runtime.EXE. Wur.GroupTool.Core.ViewModels C:\Projects\FB-IT\grouptool\sources\Wur.GroupTool\Wur.GroupTool.Core.ViewModels\ViewModels\Web\PlayGround.tt 1
是否有可能只是因为它不存在而找不到它。我的目录中没有 4.2.2.0 版本:
最佳答案
SDK版本不匹配
看来,当您安装最新的 Visual Studio(我有 16.8.3)时 - MSBuildLocator
默认使用 .NET 5 MSBuild:
JsonConvert.SerializeObject(MSBuildLocator.QueryVisualStudioInstances(VisualStudioInstanceQueryOptions.Default));
// ouputs in VS 2019:
// [{"Version":"5.0.101","VisualStudioRootPath":"C:\\Program Files\\dotnet\\sdk\\5.0.101\\","Name":".NET Core SDK","MSBuildPath":"C:\\Program Files\\dotnet\\sdk\\5.0.101\\","DiscoveryType":4}]
// just thought I'd try the same in LINQPad 5 and here's the output:
// [{"Version":{"Major":16,"Minor":8,"Build":30804,"Revision":86,"MajorRevision":0,"MinorRevision":86},"VisualStudioRootPath":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community","Name":"Visual Studio Community 2019","MSBuildPath":"C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\MSBuild\\Current\\Bin","DiscoveryType":2}]
当您执行MSBuildLocator.RegisterDefaults()
时,它会从上面的列表中获取第一个实例。
然后,使用 .NET 5 MSBuild 加载 .NET Core 3.1 项目似乎会出现错误:
Msbuild failed when processing the file '...' with message: The SDK resolver type "WorkloadSdkResolver" failed to load. Could not load file or assembly 'System.Runtime, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. The system cannot find the file specified.
但是,您可以告诉 MSBuidLocator 从特定 SDK 位置初始化环境:MSBuildLocator.RegisterMSBuildPath 。所以我尝试更新您的 Workspace
getter,如下所示:
public MSBuildWorkspace Workspace
{
get
{
if (_Workspace == null)
{
MSBuildLocator.RegisterMSBuildPath("C:\\Program Files\\dotnet\\sdk\\3.1.404");// your version might be different, check `dotnet --list-sdks`
_Workspace = MSBuildWorkspace.Create();
}
return _Workspace;
}
}
然后我必须遵循诊断输出并安装以下软件包:
<PackageReference Include="Microsoft.NET.HostModel" Version="3.1.6" />
<PackageReference Include="NuGet.Packaging" Version="5.8.0" />
<PackageReference Include="NuGet.ProjectModel" Version="5.8.0" />
将软件包安装到我的项目中后 - 我能够成功地在我的测试解决方案中列出类。
还有一件事
可能会让您绊倒的是缺少对 Microsoft.CodeAnalysis.CSharp.Workspaces
的引用(请参阅 this SO answer 了解更多背景信息)。
所以我最终像这样改变了你的构造函数:
public RoslynProjectProvider(string pathToSolution, string projectName)
{
var _ = typeof(Microsoft.CodeAnalysis.CSharp.Formatting.CSharpFormattingOptions); // this line forces a reference so MSBuild loads the assembly in question.
PathToSolution = pathToSolution;
ProjectName = projectName;
}
我已将完整的工作示例发布到 GitHub如果您想查看一下,但它几乎是您打包在 VS 中运行的所有代码。
关于c# - 使用 MSBuildWorkspace 加载解决方案和项目时出现诊断错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65268617/