[料理佳餚] .NET Core Console App 如何用組態(Debug|Release)來決定該輸出哪些設定檔?

以往我們都是透過組態(Debug|Release)來輸出不同環境的設定,這件事情到了 ASP.NET Core 則改由環境變數(Environment Variables)來控制,至於 Console App,網路上查到的資料也都是教我們用環境變數來控制設定的輸出居多,難道我們不能跟以前一樣使用組態來控制嗎?

答案當然是可以的,這邊要先說明一件事,組態跟環境變數壓根沒啥關係,選擇哪一個組態並不會影響環境變數,也就是說我們可以用 Debug 組態建置/發佈,但是環境變數可以是 Production。

準備 *.Debug.json 及 *.Release.json 設定檔

第一步當然就是準備不同組態對應的設定檔,這邊我的設定檔名稱就假設是 appsettings,那麼我會多準備一個 appsettings.json,目的是把 appsettings.Debug.jsonappsettings.Release.json Grouping 起來,方法也很簡單,在專案檔中我們加入 <DependentUpon> 標籤即可。

為了待會兒測試時可以看出差異,我特地將這三個設定檔的內容做了一點區隔。

<Choose> ... <When> ... <Otherwise>

接下來就是關鍵了,我們要修改專案檔,使用 <Choose> ... <When> ... <Otherwise> 的標籤,用來告訴建置器說,在建置時根據不同的條件採用不同的專案配置,所以底下我就針對 Debug 組態Release 組態、及其他組態進行修改。

<Project Sdk="Microsoft.NET.Sdk">

  ...

  <Choose>
    <!--When Debug-->
    <When Condition="'$(Configuration)' == 'Debug'">
      <ItemGroup>
        <None Update="appsettings.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="appsettings.Debug.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
        <None Update="appsettings.Release.json">
          <CopyToOutputDirectory>Never</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
      </ItemGroup>
    </When>

    <!--When Release-->
    <When Condition="'$(Configuration)' == 'Release'">
      <ItemGroup>
        <None Update="appsettings.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="appsettings.Debug.json">
          <CopyToOutputDirectory>Never</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
        <None Update="appsettings.Release.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
      </ItemGroup>
    </When>

    <!--Otherwise-->
    <Otherwise>
      <ItemGroup>
        <None Update="appsettings.json">
          <CopyToOutputDirectory>Always</CopyToOutputDirectory>
        </None>
        <None Update="appsettings.Debug.json">
          <CopyToOutputDirectory>Never</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
        <None Update="appsettings.Release.json">
          <CopyToOutputDirectory>Never</CopyToOutputDirectory>
          <DependentUpon>appsettings.json</DependentUpon>
        </None>
      </ItemGroup>
    </Otherwise>
  </Choose>

  ...

</Project>

進行測試

我們引入 Microsoft.Extensions.Configuration.Json 套件,讀入設定檔,建立 IConfigurationRoot 實例,然後印出 DB 的連線字串。

internal class Program
{
    private static void Main(string[] args)
    {
        var configurationRoot = new ConfigurationBuilder().SetBasePath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location))
            .AddJsonFile("appsettings.json")
            .AddJsonFile("appsettings.Debug.json", true)
            .AddJsonFile("appsettings.Release.json", true)
            .Build();

        Console.WriteLine(configurationRoot.GetConnectionString("DB"));
        Console.Read();
    }
}

可以看到,不同組態讀到的 DB 連線字串都不一樣。

這個方法就給不想使用環境變數控制設定輸出的朋友參考,不過我覺得還是不夠簡便,如果有更簡便的解法,還請不吝告知,感謝。

參考資料

C# 指南 ASP.NET 教學 ASP.NET MVC 指引
Azure SQL Database 教學 SQL Server 教學 Xamarin.Forms 教學