はじめに
.NET Framework で作成した自社製ライブラリーを、.NET 7 に移植することにした。
.NET Framework では設定ファイルは、App.config (XML 形式)を使用していたが、.NET(旧名 .NET Core)からは、appsettings.json(JSON 形式)が推奨されている。
前回は、コメントに関する記事を書きました。
今回はマッピングについて書いていきます。要はJSONのデシリアライズですね。
この記事はあくまで、IConfiguration
を使用することを前提としています。
マッピング
設定ファイルの appsettings.json
を用意します。
{
"appSettings": {
"foo": "Bob",
"bar": 42
}
}
マッピング用のクラスを用意します。
public class Settings
{
public string Foo { get; set; } = "";
public int Bar { get; set; }
}
設定ファイルの appsettings.json
を読み込みます。
var config = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", false)
.Build()
Getが見つからない
var settings = config.GetSection("appSettings").Get<Settings>();
ネット上でマッピングするのに、Get<T>()
や Bind
などを使用した例が記載されているがインテリセンスに出てこないのである。よく見れば参考した記事はどれも ASP.NET Core
の記事ばかり。コンソールやクラスライブラリー等では使えないの?
「C# Configuration get not found」って英語で検索したトップ記事に回答があった。
Install the NuGet package:
Microsoft.Extensions.Configuration.Binder
https://stackoverflow.com/questions/36694099/iconfiguration-does-not-contain-a-definition-for-get
結果
インストールすることで、Get<T>()
や Bind
が使用できるようになった。
Setting クラスにマッピングできています。
Get() を使用
var settings = config.GetSection("appSettings").Get<Settings>();
Bind を使用
var settings = new Settings();
config.Bind("appSettings", settings);
マッピング(属性指定)
下記サイトにあるようにオブジェクトをJSONにシリアライズする際には、DataMember
属性を付与し、Name
に JSONのキーを指定することができた。またSystem.Text.Json
の場合なら、JsonPropertyName
属性となる。
DataMember
属性やJsonPropertyName
属性を指定しても駄目だったので、 Configuration
で同じことが出来ないか検索してみた。
ConfigurationKeyNameAttribute Classが、.NET 6 からサポートされ、ConfigurationKeyName
が使用できるようになりました。
IgnoreDataMember属性 は見当たらないので、無視は出来なそう。
[ConfigurationKeyName(Name = "Named_Property")]
public string NamedProperty { get; set; }
サンプルソース
複数のデータベースを共通化するクラスを作成するため、接続情報としてdatabase.json
を設定した。
{
"dbSettings":{
"dbType":"SQLServer",
"connection":[
{
// 接続名
"@name":"PostgreSQL",
// 接続名
"connectionString":"Server=localhost;Port=5432;User Id=test;Password=P@ssw0rd;Database=test;CommandTimeout=600;"
},
{
// 接続名
"@name":"SQLServer",
// 接続名
"connectionString":"Data Source=localhost;Initial Catalog=ServerWatch;User ID=Test;Password=P@ssw0rd;TrustServerCertificate=True;"
},
{
// 接続名
"@name":"Oracle",
// 接続名
"connectionString":"Data Source=(DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521))(CONNECT_DATA=(SERVICE_NAME=TEST.DB))); User Id=test; Password=P@ssw0rd"
}
]
}
}
プロパティ名とキー名が不一致でも、ConfigurationKeyName
属性を使用してマッピングするキーを指定できます。
public class DBSettingData
{
public string DBType { get; set; } = "";
[ConfigurationKeyName("connection")]
public DbConnections DBConnections { get; set; } = new DbConnections();
}
public class DbConnections : List<DbConnection>
{
private int IndexOf(string name)
{
for (int i = 0; i < Count; i++)
{
DbConnection con = base[i];
if (con.Name == name)
return i;
}
return -1;
}
public DbConnection this[string name]
{
get
{
foreach (DbConnection con in this)
{
if (con.Name == name)
return con;
}
return null;
}
set
{
int i = IndexOf(name);
if (i == -1)
Add(value);
else
base[i] = value;
}
}
}
public class DbConnection
{
[ConfigurationKeyName("@name")]
public string Name { get; set; } = "";
public string ConnectionString { get; set; } = "";
}
データベース設定情報 database.json
を読み込みます。
設定情報のDBType:SQLServer
なので、ConnectionString
には、SQLServerの接続文字列がセットされます。
using Microsoft.Extensions.Configuration;
public class DatabaseInfo
{
// データベース種類定義
public const string DB_TYPE_POSTGRESQL = "PostgreSQL";
public const string DB_TYPE_SQLSERVERL = "SQLServer";
public const string DB_TYPE_ORACLE = "Oracle";
public const string DB_INFO_JSON_FILENAME = "database.json";
public const string DB_INFO_DEFAULT_SECTION = "dbSettings";
// データベースの種類
public string DBType { get; set; } = "";
// データベースの接続情報
public string ConnectionString { get; set; }
/// <summary>
/// コンストラクタ
/// </summary>
public DatabaseInfo(string path)
{
SetConnectionInfo(path, DB_INFO_DEFAULT_SECTION);
}
/// <summary>
/// DB情報をセットします。
/// </summary>
/// <param name="path">データベース接続情報パス名</param>
/// <param name="section">セクション名</param>
public void SetConnectionInfo(string path, string section)
{
try
{
var dbs = new DBSettingData();
var config = new ConfigurationBuilder()
.AddJsonFile(path)
.Build();
config.Bind(section, dbs);
// データベースの種類セット
DBType = dbs.DBType;
// 接続文字列の情報セット
ConnectionString = dbs.DBConnections[DBType].ConnectionString;
}
catch
{
throw;
}
}
}
最後に
まだここらへんに関して検索する限りだと、日本では情報がなかなか見当たらないですね。
なので、検索キーを英語にして検索するなど工夫する必要があります。
ConfigurationKeyName
など一旦キーワードが見つかれば情報が出て来たりしますが、自分自身で発信していくしかないですね。
IConfiguration
はJSON以外にも環境変数やコマンドラインパラメータで指定した設定情報などが読み込める。
単にJSONのみならSystem.Text.Json
を使えばいい気もする。属性で色々出来そうだし。