title: 分析器/源生成器添加項目依賴的方式 date: 2024-01-19 categories: 編程 tags: - C# - .NET - Roslyn 前言 寫分析器(源生成器)時經常需要引用別的包,但直接引用是無法運行的。 下麵我們分不同情況來討論在分析器項目如何對依賴進行引用。 ...
title: 分析器/源生成器添加項目依賴的方式
date: 2024-01-19
categories: 編程
tags:
- C#
- .NET
- Roslyn
前言
寫分析器(源生成器)時經常需要引用別的包,但直接引用是無法運行的。
下麵我們分不同情況來討論在分析器項目如何對依賴進行引用。
下圖中“包引用”指PackageReference
,“項目引用”指ProjectReference
。
其中項目引用是通過dll文件傳遞的,包引用是通過nupkg文件傳遞的,
最大的區別是項目引用預設不可以傳遞,而包引用預設可以傳遞。
引用方法
雖然有三種及更多項目組織方式,但解決思路是相同的,原理是將需要引用的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)\lib\netstandard2.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中。