Bind IConfiguration to C# Record Type

5.6k views Asked by At

I would like to bind configuration to record type.

This is definition of configuration type (it is without parameterless constructor):

public record AppConfiguration(string ConnectionString);

This is sample Main method:

public static void Main(string[] args)
{
    var configuration = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    AppConfiguration appConfig = new(); // error
    configuration.GetSection("app").Bind(appConfig);
}

If I convert definition to this:

public record AppConfiguration
{
    public string ConnectionString {get; init;}
}

it works as expected, but I would rather use "single line" definition of the record. Are records right way for this use case?

4

There are 4 answers

0
Marco Luzzara On

The problem with your first approach is that with the single-line declaration you have automatically defined the primary constructor, which

causes the implicitly declared default class constructor, if present, to be suppressed.

In the second case the primary constructor is the parameterless constructor, so it works as expected. Just to clear up any doubts, the init accessor is backwards compatible, so even if ConnectionString is not directly initialized, it takes the value null. The Bind method will correctly fill it using reflection, I guess.

1
Paul Hiles On

I have created a tiny NuGet package to handle binding config to positional records or classes without parameterless constructors.

If you reference the package then you just need a single line:

configuration.Bind<AppConfiguration>();

If your config file section doesn't match the type name then you can pass the section name:

configuration.Bind<AppConfiguration>("app");
1
Ian Kemp On

The ability to bind configuration sections to records has been raised as an issue with the .NET team and implemented for .NET 7+ so once you upgrade to that version, this will Just Work­­™:

var appConfig = config.GetSection("app").Get<AppConfiguration>();

It has also been added to the Microsoft.Extensions.Configuration.Binder NuGet package as of version 7.0.0 and above.

Alternatively, you can use Paul Hiles' NuGet package (link in his answer).

0
Larry Smith On

I was just running into this issue. In the time since your question was posted, it looks like this capability has been added via nuget package reference to Microsoft.Extensions.Configuration.Binder. When you add this nuget package, you then get to use Get() on the config section:

 var appConfig = config.GetSection("app").Get<AppConfiguration>();