分析器/源生成器添加项目依赖的方式

  • 分析器/源生成器添加项目依赖的方式已关闭评论
  • 137 次浏览
  • A+
所属分类:.NET技术
摘要

写分析器(源生成器)时经常需要引用别的包,但直接引用是无法运行的。
下面我们分不同情况来讨论在分析器项目如何对依赖进行引用。

title: 分析器/源生成器添加项目依赖的方式 date: 2024-01-19 categories: 编程 tags: - C# - .NET - Roslyn 

前言

写分析器(源生成器)时经常需要引用别的包,但直接引用是无法运行的。
下面我们分不同情况来讨论在分析器项目如何对依赖进行引用。

下图中“包引用”指PackageReference,“项目引用”指ProjectReference

其中项目引用是通过dll文件传递的,包引用是通过nupkg文件传递的,
最大的区别是项目引用默认不可以传递,而包引用默认可以传递。

flowchart TD A1--项目引用-->A2 GA--包引用-->A3 GB1--包引用-->B2 GB2--包引用-->B3 C1--项目引用-->C2 subgraph G1[单NuGet包项目] subgraph GA[NuGet包] direction TB A1[分析器项目] A2[NuGet包主项目] end A3[用户项目] end subgraph G2[NuGet包传递] subgraph GB1[分析器NuGet包] B1[分析器项目] end subgraph GB2[NuGet包] B2[NuGet包项目] end B3[用户项目] end subgraph G3[直接项目引用] C1[分析器项目] C2[用户项目] end

引用方法

虽然有三种及更多项目组织方式,但解决思路是相同的,原理是将需要引用的dll路径告诉分析器即可。

如何写

在csproj项目文件中用以下语句[1]即可实现这个功能(以System.Text.Json为例):

<ItemGroup>     <PackageReference Include="System.Text.Json" Version="8.0.1" GeneratePathProperty="true" PrivateAssets="all" ReferenceOutputAssembly="false" /> </ItemGroup>  <PropertyGroup>     <GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn> </PropertyGroup>  <Target Name="GetDependencyTargetPaths">     <ItemGroup>         <TargetPathWithTargetPlatformMoniker Include="$(PkgSystem_Text_Json)libnetstandard2.0*.dll" IncludeRuntimeDependency="false" />     </ItemGroup> </Target> 

第一部分ItemGroup是引用包项目。其中:

  • PrivateAssets指定了这个依赖不会传递给用户项目,如果需要传递的话,则无需指定这句;

  • ReferenceOutputAssembly是是否引用这个包,例如“NuGet包传递”模式中,也许只有分析器项目才需要使用这个包,NuGet包主项目并不需要它,即可指定这个属性;

  • GeneratePathProperty是生成PkgSystem_Text_Json属性,我们可以用$(PkgSystem_Text_Json)的方法去获取这个包的dll所在路径,规律是Pkg+包名,其中包名中的替换为下划线

第二部分PropertyGroup是指定需要GetDependencyTargetPaths这个Target

第三部分Target指定了GetDependencyTargetPaths具体如何实现,即将告诉编译器指定dll的路径。

写在哪

一个解决方案有很多项目,那上面的问题应该写在哪呢?有一个很容易的判断标准:

写在用户项目引用的对象上。

举例来说,例如“直接项目引用”中,用户项目引用的是分析器项目的dll,所以我们应该将上面那些写在分析器的csproj中。

“NuGet包传递”比较特殊,NuGet包项目引用了分析器项目的nupkg后传递给了用户项目,本质上引用的是分析器项目(因为用户项目也可以直接引用分析器项目NuGet包),所以我们应该写在分析器的csproj中。

“单NuGet包项目”中,NuGet包主项目会将分析器项目的dll包含进输出的nupkg中,所以我们应该写在NuGet包主项目的csproj中。


  1. GitHub Disscussion ↩︎