Poy Chang's Blog

在 Visual Studio 中自訂檔案巢狀結構

Visual Studio 的方案總管(Solution Explorer)內建了將檔案做巢狀結構的功能,可以讓我們更清楚的查看相依的檔案關係,這個功能會根據專案類型而變更檢視方式,在 ASP.NET Core 這類 Web 專案中會被套用,但我們也可以在其他類型的專案中使用相同的巢狀結構檢視。

網站開發者應該會在 ASP.NET Core 的專案中,發現 appsettings.json 這類的檔案會有巢狀結構,但當我們想要在其他類型的專案,例如 Console App 或 Class Library 專案,也使用這樣的檔案巢狀結構時,會發現預設是沒有效果的,這時候有幾種方式可以調整。

調整專案檔

你可以調整 .csproj 專案檔來達到這樣的效果。

我們期待的專案的檔案結構會像是下圖右邊,appsettings.json 會有檔案階層,讓檔案結構看起來比較順眼。

建立 appsettings.json 的檔案階層

要做到檔案階層的收折,要來調整 .csproj 專案檔,請參考下列程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
<Project Sdk="Microsoft.NET.Sdk">
<!-- 略... -->
<ItemGroup>
<None Update="appsettings.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="appsettings.*.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
<DependentUpon>appsettings.json</DependentUpon>
</None>
</ItemGroup>
</Project>

接著把每個檔案都加進去 ItemGroup 並做對應的設定,或者可以使用 * 萬用字元來將多個檔案一起做設定。這裡有兩個屬性要知道:

  • CopyToOutputDirectory 設定是否複製至輸出資料夾,有以下三個設定值
    • Never 不複製至輸出資料夾
    • Always 總是複製至輸出資料夾
    • PreserveNewest 有更新時才複製至輸出資料夾
  • DependentUpon 設定此檔案依賴於哪個主要檔案

如此一來,我們的專案的檔案結構就變得漂亮多了。

但這個方式的缺點是,必須針對每個檔案都要做設定,如果檔案數量很多的話,會變得很麻煩。

使用 .filenesting.json

如果你所開發的專案沒有像是 .csproj 的專案檔,或者不想要改動專案檔內的設定時,要怎樣啟動 Visual Studio 方案總管所提供的檔案巢狀功能呢?

Visual Studio 會自動偵測專案資料夾中是否有一個名為 .filenesting.json 的設定檔,

只要你在專案資料夾中加入一個 .filenesting.json 設定檔,內容不需要做任何修改,Visual Studio 方案總管的檔案巢狀功能也會自動啟動。

當然你也可以在這個檔案中做一些客製設定,例如,我只想針對 .cs 的檔案做檔案巢狀設定,那麼可以在 .filenesting.json 設定檔中加入下列程式碼:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"help": "https://go.microsoft.com/fwlink/?linkid=866610",
"dependentFileProviders": {
"add": {
"pathSegment": {
"add": {
".*": [
".cs"
]
}

}
}
}
}

更詳細的設定選項,請參考 File nesting in Solution Explorer

另外,Visual Studio 的預設值不是以 .filenesting.json 檔案的方式存在,但可以透過建立新的檢視設定來查看預設值,預設值內容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
"help": "https://go.microsoft.com/fwlink/?linkid=866610",
"root": true,
"dependentFileProviders": {
"add": {
"addedExtension": {},
"pathSegment": {
"add": {
".*": [".js", ".css", ".html", ".htm", ".less", ".scss", ".coffee", ".iced", ".config", ".cs", ".vb", ".json"]
}
},
"extensionToExtension": {
"add": {
".js": [".coffee", ".iced", ".ts", ".tsx", ".jsx"],
".css": [".less", ".scss", ".sass", ".styl"],
".html": [".md", ".mdown", ".markdown", ".mdwn"],
".map": [".js", ".css"],
".svgz": [".svg"],
".designer.cs": [".resx"],
".cs.d.ts": [".cs"]
}
},
"fileToFile": {
"add": {
".bowerrc": ["bower.json"],
".npmrc": ["package.json"],
"npm-shrinkwrap.json": ["package.json"],
"yarn.lock": ["package.json"],
".yarnclean": ["package.json"],
".yarnignore": ["package.json"],
".yarn-integrity": ["package.json"],
".yarnrc": ["package.json"],
"package-lock.json": ["package.json"]
}
},
"fileSuffixToExtension": {
"add": {
"-vsdoc.js": [".js"]
}
},
"allExtensions": {
"add": {}
}
}
}
}

後記

我個人在寫 .NET 專案的時候,對於功能多又複雜的 Class 類別檔,喜歡用 partial 部分類別關鍵字修飾詞並且拆分成多個檔案,如此一來可以讓我更容易管理檔案內的方法與屬性,而且可以更容易的根據使用目的來分門別類。

以下就是使用 partial 部分類別搭配檔案巢狀來整理程式碼檔案,即使是在同一個類別下,可以更清楚的根據用途來分出每個方法或屬性的群組。

使用 partial 部分類別搭配檔案巢狀來整理程式碼檔案


參考資料: