相关文章推荐
被表白的八宝粥  ·  java.net.UnknownHostEx ...·  1 年前    · 
打盹的水煮肉  ·  解决 ...·  1 年前    · 
俊秀的凳子  ·  WSL 安装CentOS + NodeJS ...·  1 年前    · 

.NET Source Generator项目在添加Nuget包后Visual Studio无法找到依赖库的解决办法

以下是一个普普通通的C#的Source Generator的项目的.csproj文件:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
	<TargetFramework>netstandard2.0</TargetFramework>
	<IsRoslynComponent>true</IsRoslynComponent>
	<LangVersion>latest</LangVersion>
  </PropertyGroup>
  <ItemGroup>
	<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
	<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" PrivateAssets="all" />
	<PackageReference Include="System.Text.Json" Version="7.0.0" PrivateAssets="all" />
  </ItemGroup>
</Project>

然而在添加了"System.Text.Json"它就开始出问题了:

warning CS8785: Generator 'SourceGenerator' failed to generate source. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'FileNotFoundException' with message 'Could not load file or assembly 'System.Text.Json, Version=7.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. 系统找不到指定的文件。'

其实这个问题不止是"System.Text.Json"后,任何Nuget包都会有这个问题。

参见:

Reference local projects in Source Generator · Discussion #47517 · dotnet/roslyn (github.com)

NuGets referenced from analyzer/source-generator should automatically include DLL's · Issue #7640 · dotnet/msbuild (github.com)

目前的解决办法是:你需要将所需的Nuget包及其所依赖的所有Nuget包全都加上,其中GeneratePathProperty要设置为true,然后添加一个Target,在其中添加一个ItemGroup,在其中为每一个Nuget包添加一个TargetPathWithTargetPlatformMoniker项,这些项将IncludeRuntimeDependency设置为False,并Include通过Nuget包路径获取的dll路径。

以我们的这个项目为例,能正确地Build的csproj配置如下:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
	<TargetFramework>netstandard2.0</TargetFramework>
	<IsRoslynComponent>true</IsRoslynComponent>
	<LangVersion>latest</LangVersion>
  </PropertyGroup>
  <ItemGroup>
	<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.3" PrivateAssets="all" />
	<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.1" PrivateAssets="all" />
	<PackageReference Include="System.Text.Json" Version="7.0.0" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="Microsoft.Bcl.AsyncInterfaces" Version="7.0.0" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.0.0" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Threading.Tasks.Extensions" Version="4.5.4" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Text.Encodings.Web" Version="7.0.0" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Buffers" Version="4.5.1" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Memory" Version="4.5.5" GeneratePathProperty="true" PrivateAssets="all" />
	<PackageReference Include="System.Numerics.Vectors" Version="4.5.0" GeneratePathProperty="true" PrivateAssets="all" />
  </ItemGroup>
  <PropertyGroup>
	<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
  </PropertyGroup>
  <Target Name="GetDependencyTargetPaths">
	<ItemGroup>
	  <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
	  <TargetPathWithTargetPlatformMoniker Include="$(PKGMicrosoft_Bcl_AsyncInterfaces)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
	  <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Runtime_CompilerServices_Unsafe)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
	  <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Threading_Tasks_Extensions)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />
	  <TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Buffers)\lib\netstandard2.0\*.dll" IncludeRuntimeDependency="false" />