admin管理员组文章数量:1391925
I'm developing a .NET 8 WorkerService project where I load configuration from multiple sources (e.g., appsettings.json
and appsettings.Development.json
). My configuration file defines a section Units
that holds an array of objects, each containing a name and an array of paths.
Here's a simplified version of my code:
Program.cs:
var builder = Host.CreateApplicationBuilder(args);
var units = builder.Configuration.GetSection("Units").Get<Unit[]>();
foreach (var unit in units)
{
foreach (var item in unit.Paths)
{
Console.WriteLine(item);
}
}
public record Unit(string Name, string[] Paths);
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"Units": [
{
"name": "test1",
"paths": [
"p1",
"p2",
"p3"
]
},
{
"name": "test2",
"paths": [
"p4",
"p5",
"p6"
]
}
]
}
appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
When I run the project, I expect the output to be:
p1
p2
p3
p4
p5
p6
However, the actual output is:
p1
p2
p3
p1
p2
p3
p4
p5
p6
p4
p5
p6
Question: Why am I getting duplicate values? Has anyone encountered this behavior before and can shed some light on what's causing it?
Any insights would be greatly appreciated!
I'm developing a .NET 8 WorkerService project where I load configuration from multiple sources (e.g., appsettings.json
and appsettings.Development.json
). My configuration file defines a section Units
that holds an array of objects, each containing a name and an array of paths.
Here's a simplified version of my code:
Program.cs:
var builder = Host.CreateApplicationBuilder(args);
var units = builder.Configuration.GetSection("Units").Get<Unit[]>();
foreach (var unit in units)
{
foreach (var item in unit.Paths)
{
Console.WriteLine(item);
}
}
public record Unit(string Name, string[] Paths);
appsettings.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"Units": [
{
"name": "test1",
"paths": [
"p1",
"p2",
"p3"
]
},
{
"name": "test2",
"paths": [
"p4",
"p5",
"p6"
]
}
]
}
appsettings.Development.json:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
When I run the project, I expect the output to be:
p1
p2
p3
p4
p5
p6
However, the actual output is:
p1
p2
p3
p1
p2
p3
p4
p5
p6
p4
p5
p6
Question: Why am I getting duplicate values? Has anyone encountered this behavior before and can shed some light on what's causing it?
Any insights would be greatly appreciated!
Share Improve this question edited Mar 14 at 16:37 Ivan Petrov 5,4622 gold badges11 silver badges24 bronze badges asked Mar 14 at 11:36 Christopher FontaineChristopher Fontaine 356 bronze badges 3- I tried to recreate your problem in a .NET 8 console app with the code you provided and I got the expected output. You're probably accidently importing the appsettings twice or something. – Shoejep Commented Mar 14 at 12:08
- @Shoejep The provided code exactly produces the behavior I described. In the accepted answer, Ivan Petrov explains the underlying cause of the duplicate binding, clarifying that the issue is due to how the configuration binder processes the record with a primary constructor. Please refer to his answer for the detailed explanation. – Christopher Fontaine Commented Mar 16 at 8:09
- 1 I realised I installed Microsoft.Extensions.Hosting 9.0.3 when trying to reproduce your issue and the issue doesn't exist there. Apologies. – Shoejep Commented Mar 17 at 9:17
1 Answer
Reset to default 1The issue is with you using a record
which by default
- doesn't have a parameterless constructor
- also has properties that even if
init
only have asetter
that configuration binding apparently uses to set values a SECOND time
Workaround if you want to continue using a record is to declare a parameterless constructor:
public record Unit(string Name, string[] Paths)
{
public Unit() : this(string.Empty, Array.Empty<string>()) { }
}
If you want to reproduce it, you can declare a normal class that resembles a record:
public class Unit
{
public Unit(string name, string[] paths)
{
Name = name;
Paths = paths;
}
public string Name { get; init }
public string[] Paths { get; init }
}
If you remove the init
- you won't get duplicate values inside the Paths
array.
So in .NET7+ where the feature of binding to classes with parameterized constructor was made available the logic seems to be:
- Execute the parameterized constructor and pick the configuration elements for the parameters based on type or some other heuristic
- If a property has a setter -> Find what is there by calling the getter and then instead of overwriting it, append to it in case of a colleciton
I couldn't find a documentation for this behavior, but the following issues might shed some light if it's a bug or a feature:
- Support immutable types with configuration binding
- [Feature Request] Allow Options service to bind config to class with parameterised ctor
- Support immutable types with configuration binding
本文标签: cUnexpected Duplicate Configuration Values in NET 8 WorkerServiceStack Overflow
版权声明:本文标题:c# - Unexpected Duplicate Configuration Values in .NET 8 WorkerService - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744659355a2618152.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论