zukucode
主にWEB関連の情報を技術メモとして発信しています。

ASP.NET Core appsettings.jsonを別プロジェクトで読み込む

ASP.NET Core DBの接続文字列を設定ファイルから取得するで、appsettings.jsonに定義した接続文字列を読み込む方法を紹介しました。

しかし、実際は接続文字列はASP.NET Coreのプロジェクトではなくデータアクセス層やインフラ層などの別プロジェクトで読み込むことが多いです。

ここでは、ASP.NET Core ソリューションを作成して複数のプロジェクトを管理するで作成したソリューションにインフラ層のクラスライブラリのプロジェクトを追加して、そのプロジェクトで設定ファイルから接続文字列を取得するように実装します。

インフラ層の作成

以下のコマンドでインフラ層のプロジェクトを作成します。

$ dotnet new classlib -o App.Infrastructure

以下のフォルダが作成されます。

  • App.Infrastructure ←作成される
  • App.Web
  • App.sln

本来はインフラ層だけではなくアプリケーション層やドメイン層も作成することが多いですが、ここでは説明の都合でインフラ層のみ作成しています。

ソリューションの追加

インフラ層のプロジェクトをソリューションに追加します。

以下のコマンドで、App.Infrastructureプロジェクトをソリューションに追加します。

$ dotnet sln add App.Infrastructure

また、Web層のプロジェクトに、インフラ層のプロジェクトを参照に追加します。

$ cd App.Web # Web層のプロジェクトに移動
$ dotnet add reference ../App.Infrastructure

パッケージのインストール

設定ファイルを読み込むためのパッケージをインフラ層のプロジェクトにインストールします。

Microsoft.Extensions.Configuration
設定ファイルを読み込みためのパッケージ
Microsoft.Extensions.Options.ConfigurationExtensions
DI(Dependency Injection)を行うためのパッケージ
$ cd App.Infrastructure # インフラ層のプロジェクトに移動
$ dotnet add package Microsoft.Extensions.Configuration
$ dotnet add package Microsoft.Extensions.Options.ConfigurationExtensions

設定内容を格納するクラスの作成

接続文字列などの設定情報を格納するクラスを作成します。

インターフェースを作成して、そのインターフェイスを実装する形で作成します。

コンストラクタで接続文字列を受け取るようにして、ローカル変数に保持します。

GetConnectionStringメソッドで外部から接続文字列をアクセスできるようにします。

IDatabaseConfig.cs
namespace App.Infrastructure.Core;

public interface IDatabaseConfig
{
    public string GetConnectionString();
}
DatabaseConfig.cs
namespace App.Infrastructure.Core;

public sealed class DatabaseConfig : IDatabaseConfig
{
    private readonly string _connectionString;

    public DatabaseConfig(string connectionString)
    {
        _connectionString = connectionString;
    }

    public string GetConnectionString() => _connectionString;
}

DIクラスの作成

DIの設定を行うクラスを作成します。

AddInfrastructureのファンクションは、ASP.NET Coreのプロジェクトから呼ばれます。

DIコンテナを管理するservicesと設定情報を管理するconfigurationをパラメータとして受け取り、設定ファイルの読み込みや、DIコンテナへの追加を行います。

DependencyInjection.cs
using App.Infrastructure.Core;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

namespace App.Infrastructure;

public static class DependencyInjection
{
    public static IServiceCollection AddInfrastructure(this IServiceCollection services, IConfiguration configuration)
    {
        // 接続文字列をパラメータにDatabaseConfigクラスのインスタンスを作成し、DIコンテナに追加する
        services.AddScoped<IDatavaseConfig>(_ => new DatabaseConfig(configuration.GetConnectionString("DefaultConnection") ?? ""));

        return services;
    }
}

Web層のProgram.csで、上記のファンクションを実行するように、処理を追加します。

Program.cs
using App.Infrastructure;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
builder.Services.AddInfrastructure(builder.Configuration);

これにより、IDatabaseConfigは設定ファイルの接続文字列をパラメータにインスタンス化されたものとして、各処理で参照することができます。

参照方法

ASP.NET Core DBの接続文字列を設定ファイルから取得するの処理をIDatabaseConfigを参照するように書き換えます。

コンストラクタインジェクションで、DIコンテナに登録したクラスを参照します。

using App.Infrastructure.Core;

    private readonly ILogger<WeatherForecastController> _logger;
    private readonly IConfiguration _configuration;
    private readonly IDatabaseConfig _databaseConfig;

    public WeatherForecastController(ILogger<WeatherForecastController> logger, IConfiguration configuration)
    public WeatherForecastController(ILogger<WeatherForecastController> logger, IDatabaseConfig databaseConfig)
    {
        _logger = logger;
        _configuration = configuration;
        _databaseConfig = databaseConfig;
    }
    
    [HttpGet]
    public IEnumerable<WeatherForecast> Get()
    {
        using var conn = new NpgsqlConnection(_configuration.GetConnectionString("DefaultConnection"));
        using var conn = new NpgsqlConnection(_databaseConfig.GetConnectionString());

今回は、データベースの設定情報のみインフラ層で定義するように修正しましたが、実際はDBアクセスクラスもインフラ層に実装することになります。

データアクセス関連の処理をすべてインフラ層に実装する方法をASP.NET Core DIできるDBクラスを作成してクリーンアーキテクチャを理解するで紹介しています。


関連記事