了解 .NET Core csproj 操作
我正在嘗試複製文件夾的內容以建構輸出。理想情況下,在相對於輸出/發布文件夾的相同路徑下。我有:
<!-- front-end files to serve --> <ItemGroup> <Folder Include="Frontend\Content"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Folder> </ItemGroup>但是,當我使用 時
dotnet publish,不會複製任何文件。這適用於我想要的配置文件 - 這是由 VS 生成的:
<ItemGroup> <None Remove="my-config.json" /> </ItemGroup> <ItemGroup> <Content Include="my-config.json"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </Content> </ItemGroup>所以我的問題是——這是什麼瘋狂?
None從語義上講,一個用屬性呼叫的元素Remove——這甚至意味著什麼?我模糊的直覺是元素相當於一個“集合”,其內容將根據該元素/集合的名稱進行操作,並且包含、排除、刪除以某種方式(?)互動以定義和細化內容的那一套。
但是然後 - 什麼是“文件夾”?什麼是“內容”?當事情加倍時會發生什麼:為什麼需要“無/刪除”組合?如果有的話 - 那是由 VS 生成的!
在文件方面,我發現:
<https://docs.microsoft.com/en-us/dotnet/core/tools/csproj#how-to-see-the-whole-project-as-msbuild-sees-it>,其中談到了編譯、嵌入式資源和無預設 glob(包括、排除和刪除 glob)。我知道什麼是 glob,我知道這些操作意味著什麼,但是這些類型的 glob 是什麼?他們如何互動?
它還指向<https://docs.microsoft.com/en-us/visualstudio/msbuild/msbuild-project-file-schema-reference?view=vs-2017>上的 MSBuild 文件,但這似乎沒用:它沒有’沒有顯示文件
None、、EmbeddedResource或Compile元素,也沒有談論我在其他範例中找到的Content和元素(由 VS 生成)。Folder事實上,我還沒有找到任何關於這一切意味著什麼的東西。
我在哪裡可以找到這方面的文件?
- 文件夾項目
<Folder>在 VS 中使用只是在解決方案資源管理器中顯示一個節點,例如讓您指向右鍵點擊“添加 > 新建…”。wwwroot是 ASP.NET Core 應用程序的經典範例,但如果您使用 VS 的“添加 > 新文件夾”功能或刪除現有文件夾中的所有文件,它將添加一個節點以將其保留在解決方案資源管理器中。
<Folder>在建構期間不使用這些項目。複製項目是根據在已知項目類型(無、內容、…)上指定的元數據確定的,而不是基於文件系統層次結構中的文件夾項目。如果要為整個層次結構指定元數據,可以執行
<Content Include="my/content/**/*" CopyToPublishDirectory="True" … />
- 包括/刪除組合
在項目文件的靜態內容中(不是在其中
<Target>應用了一些不同的規則),MSBuild 允許對項目集合進行三種操作:
- 包括:將一個項目添加到指定項目類型的項目的“集合”中
- 更新:更改指定項目類型項目的元數據
- 刪除:從“集合”中刪除項目
這意味著如果你這樣做
<None Include="foo.txt" /> <Content Include="foo.txt" />然後
@(None)和@(Content)集合都將包含foo.txt. 這對於建構系統來說並不是真正的問題(除非您指定要將它們都複製到輸出中 - 這會導致輸出路徑衝突的錯誤),但是對於向您顯示項目中的文件及其屬性的工具來說可能會造成棘手的情況。如果
foo.txt列出為和None,那麼 IDE(VS、Rider、VS/Mac 等)工具必須做出艱難的決定,決定向您顯示該文件的內容。Content``EmbeddedResource為了緩解這個問題,最好確保一個文件僅被列為這些“建構操作”項類型之一,這樣 IDE 就不會被混淆(也不會被使用者混淆)。
那麼為什麼要從中刪除文件
None呢?新的“SDK 風格”項目添加了很多預設值。它們基本上包含類似(簡化的!!):
<None Include="**/*" />因此,如果要將文件更改為嵌入資源或內容項,則應從
@(None)集合中刪除該文件。如果您不需要更改項目類型,您還可以使用
Update:<None Update="some/content/**/*" CopyToOutputDirectory="True" />
- 那麼下面的那些東西是做什麼的
<ItemGroup>呢?這些定義本身沒有任何作用。他們只是填充/更改“項目”的集合。您甚至可以創建自己的並在以後使用它們:
<MyCoolFiles Include="cool/files/**/*;other/cool/files/**/*" /> <None Remove="@(MyCoolFiles)" /> <Content Include="@(MyCoolFiles)" CopyToPublishDirectory="True" /> <Target Name="PrintCoolFiles" BeforeTargets="BeforeBuild"> <Message Importance="high" Text="These are my cool files: @(MyCoolFiles)" /> </Target>關鍵是建構邏輯的某些部分會查找他們知道的項目並使用它們。
計算編譯器輸入的部分將查看
Compile和EmbeddedResource項目,確定將哪些文件複製到輸出目錄的部分將查找具有特定元數據集的各種項目(None、Content和其他一些 IIRC )。EmbeddedResource新的項目類型可以定義自己的項目類型,通過擴展點在 VS 的解決方案資源管理器中列出。
但是 VS 只會在解決方案資源管理器中顯示以這種方式配置的項目類型的項目。對於這些項目類型,沒有在多個項目中列出一個文件是有意義的。