[C#]Binding appsettings.json to Classes for Type-Safe Configuration

目次

Overview

In the .NET Generic Host, it is common to read values from configuration files like appsettings.json. Instead of using string keys to get values manually, you can map (bind) these sections to a defined class (POCO). This method removes “magic strings” (like “KeyString”) and allows you to use IntelliSense, making your code type-safe.

Specifications (Input/Output)

Input

  • appsettings.json (Configuration file)

Output

  • An object instance that holds the configuration values as properties.

Features

  • Retrieve a JSON section using IConfiguration.
  • Automatically assign values to C# class properties using the Bind method.

Basic Usage

Create a class that matches the structure of the JSON you want to read. Then, combine GetSection and Bind.

// Create an instance of the configuration class
var config = new SystemConfig();

// Bind the values from the "SystemConfig" section into the instance
_configuration.GetSection("SystemConfig").Bind(config);

Full Code

This is the complete code refactored for practical use. It includes the configuration class definition and uses Dependency Injection (DI) to read the values.

1. appsettings.json

Place this file in the project root. In the file properties, set “Copy to Output Directory” to “Copy if newer” or “Copy always.”

{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "SystemConfig": {
    "ApplicationName": "BatchProcessor",
    "Version": "1.0.5",
    "IsDebugMode": true
  }
}

2. ConfigLoaderWorker.cs

This is the worker class implementation that reads the configuration values and prints them to the console.

using System;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration; // Required for the Bind method
using Microsoft.Extensions.Logging;

namespace TaskRunnerApp
{
    // 1. Class for mapping configuration values (POCO)
    // Property names should match the JSON keys (case-insensitive)
    public class SystemConfig
    {
        public string ApplicationName { get; set; } = string.Empty;
        public string Version { get; set; } = string.Empty;
        public bool IsDebugMode { get; set; }
    }

    // 2. Worker class that performs the process
    public class ConfigLoaderWorker : IConsoleWorker
    {
        private readonly IConfiguration _configuration;
        private readonly ILogger<ConfigLoaderWorker> _logger;

        // Receive IConfiguration from the DI container
        public ConfigLoaderWorker(IConfiguration configuration, ILogger<ConfigLoaderWorker> logger)
        {
            _configuration = configuration;
            _logger = logger;
        }

        public Task RunAsync()
        {
            _logger.LogInformation("--- Starting to read configuration values ---");

            // Pattern A: Get values individually by specifying keys (returns a string)
            string rawAppName = _configuration["SystemConfig:ApplicationName"];
            Console.WriteLine($"[Individual] AppName: {rawAppName}");

            // Pattern B: Bind everything to a class (Recommended)
            var config = new SystemConfig();
            
            // Assign the specified section ("SystemConfig") to the class
            // Requires NuGet package: Microsoft.Extensions.Configuration.Binder
            _configuration.GetSection("SystemConfig").Bind(config);

            // Access values safely as class properties
            Console.WriteLine($"[Bound Class] Name    : {config.ApplicationName}");
            Console.WriteLine($"[Bound Class] Ver     : {config.Version}");
            Console.WriteLine($"[Bound Class] Debug   : {config.IsDebugMode}"); // Handled as a bool type

            return Task.CompletedTask;
        }
    }

    // Reference interface for execution
    public interface IConsoleWorker
    {
        Task RunAsync();
    }
}

Execution Result Example

info: TaskRunnerApp.ConfigLoaderWorker[0]
      --- Starting to read configuration values ---
[Individual] AppName: BatchProcessor
[Bound Class] Name    : BatchProcessor
[Bound Class] Ver     : 1.0.5
[Bound Class] Debug   : True

Customization Points

The Get<T> Method

You can use an extension method to create the instance and bind the values in a single line.

var config = _configuration.GetSection("SystemConfig").Get<SystemConfig>();

Using the Options Pattern

If you register the configuration in your setup using services.Configure<SystemConfig>(...), you can receive it as IOptions<SystemConfig> in your constructor. This makes dependencies clearer.

Important Points

Missing NuGet Packages

If you see an error saying the Bind or Get methods cannot be found, check if the Microsoft.Extensions.Configuration.Binder package is included in your project.

Property Accessibility

The properties you want to bind must be public and have a set accessor (or init). Values will not be set for properties that only have a get accessor.

Environment Variable Priority

By default, environment variables often have higher priority than JSON files. For example, if an environment variable named SystemConfig__IsDebugMode is set on the OS, it will overwrite the value in your JSON file.

Summary

By binding appsettings.json values to a class, you can avoid manual type conversion and significantly improve code readability and maintainability. It is recommended to minimize access using string keys and instead use mapping to POCO classes with Bind or Get<T>. This ensures that you can safely handle changes or additions to configuration items just by updating the class definition.

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

私が勉強したこと、実践したこと、してることを書いているブログです。
主に資産運用について書いていたのですが、
最近はプログラミングに興味があるので、今はそればっかりです。

目次