【聲明】關於類別程式庫是否該自行讀取 config 設定檔?靜態屬性或方法是否為適當設計?在開發人員間仍存在意見分歧。基於現實世界這類應用仍算常見(例如:NLog.config、 JsonConvert.DefaultSettings...),而開發習慣調整非一朝一夕可以改變,這篇文章聚焦舊元件改版 .NET Standard 類別程式庫,儘量沿襲舊寫法降低改版衝擊,故會擱置該不該使用靜態屬性、方法以及讀取設定檔的爭議,忽略改成 OOO 或 XXX 寫法比較好的相關討論。

陸續想把一些舊元件升級成 .NET Standard 版本(延伸閱讀: .NET Standard 2.0 是什麼?可以吃嗎?),我最常遇到的問題是 .config 的 appSetting 讀取問題,先前在淺談 .NET 類別程式庫跨平台開發有找到 .csproj 宣告 <TargetFrameworks>netstanard2.0;net461</TargetFrameworks>,再針對 .NET Framework 4.x 加參照,用 #if NET4XX ... #else ... #endif 為不同平台寫不同程式碼,最後編譯成多套 dll 的做法,可行歸可行,但手續複瑣,感覺一點也不優雅。

今天搞 Side Project 再遇到這個老問題,想找找是否有更好解法,爬文查到好東西:

.NET Standard 2.0 有提供 System.Configuration.ConfigurationManager NuGet Package,可以不用為此多設 TargetFramework,更妙的是 - 它還能讓 .NET Core 專案支援 .config appSettings 設定。

下面是我的實測,共有 AspNet5 (.NET 4.7.2)、AspNetCore (.NET Core 3.1)、ConsoleCore (.NET Core 3.1)、ConsoleFX (.NET 4.7.1)、MyLib (.NET Standard 2.0):

MyLib 專案參照了 System.Configuration.ConfigurationManager NuGet Package 就可以大大方方讀取 AppSettings["..."],JobUtil.cs 長這樣:

using System;

namespace MyLib
{
    public class JobUtil
    {
        public static int BatchSize
        {
            get
            {
                return int.Parse(
                    //TODO: 省略設定值需為數字檢核
                    System.Configuration.ConfigurationManager.AppSettings["BatchSize"] ?? "100");
            }
        }
    }

}

其他四個專案都引用了 MyLib,有趣的是上圖 1、2 箭頭所指處,我居然在 .NET Core 專案裡加入傳統上是 .NET Framework 在用的 App.config,其內容如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="BatchSize" value="255"/>
  </appSettings>  
</configuration>

然後,神奇的事發生了!

原來,.NET Core 設定值除了放在新推出的格式 - appSettings.json (延伸閱讀: ASP.NET Core 練習 - 從類別程式庫讀取網站 appSettings) 外,也能相前相容使用 App.config appSetting XML 設定。ConsoleCore 專案跑出一個 ConsoleCore.dll.config (跟 .NET 4.X 用 .exe.config 檔名不同,但是一樣的東西),執行結果 MyLib.JobUtil.BatchSize 是 ConsoleCore.dll.config 中的 appSetting 值 255,而不是預設值 100:

不意外地,這個做法搬到 Linux 執行也暢行無阻:

而 AspNetCore 專案也一樣,可由 AspNetCore.dll.config (注意:不是 web.config) 的 appSetting 決定 BatchSize:

但回頭測試 AspNet5 及 ConsoleFX 則遇到小問題,出現 System.IO.FileNotFoundException: 'Could not load file or assembly 'System.Configuration.ConfigurationManager, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.' 錯誤:

爬文有人回報相似狀況,我對 .NET Standard 的了解不夠通透無力破案,目前知道的 Workaround 是在 Console .NET 4.x 及 ASP.NET 5 專案明確引用 System.Configuration.ConfigurationManager NuGet Package 即可排除問題。而這兩個 .NET 4.x 專案,appSetting 設定還是存在熟悉的老地方 ConsoleFX.exe.config 跟 web.config 裡。

【結論】

原本只是想找到在 .NET Standard 類別程式庫簡便讀取 .config appSetting 的方法,意外發現了 System.Configuration.ConfigurationManager NuGet Package,原來 .NET Core 程式除了 appSettings.json,也還能繼續支援舊時代的 XML .config 檔 appSetting,未來開發 .NET Core 程式,又多了一項新選擇。

This article talks about how to read .config XML appSetting in .NET Standard library, .NET Core by System.Configuration.ConfigurationManager NuGet Package.


Comments

# by Soon

教可以大大方方 => 就可以大大方方?

# by Jeffrey

to Soon, 錯字魂正常發揮... Orz 謝謝指正。

# by kevin

第一次提到 System.Configration.ConfigurationManager 調整為這個才找的到 => System.Configuration.ConfigurationManager

# by Jeffrey

to kevin, 謝謝指正,已修正。

Post a comment