Description
The Configuration.Binder source generator emits property and type names verbatim into identifier position without escaping C# keywords. If a configuration model has a property whose name is a keyword (declared with @, e.g. @base, @event), the generated validator emits e.g. base instead of @base, which does not compile.
Reproduction Steps
// sln
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net11.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<EnableConfigurationBindingGenerator>true</EnableConfigurationBindingGenerator>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.9" />
</ItemGroup>
</Project>
// Program.cs
using Microsoft.Extensions.Configuration;
internal class Program
{
private static void Main(string[] args)
{
ConfigurationManager manager = new();
MyConfiguration? options = manager.GetSection("My").Get<MyConfiguration>();
}
}
class MyConfiguration(string @base, string @event)
{
public string Base { get; } = @base;
public string Event { get; } = @event;
}
Expected behavior
The generated code compiles, emitting configuration.@base (or otherwise escaping keyword identifiers).
Actual behavior
Build fails. The generated BindingExtensions.g.cs contains (note the unescaped base and event):
public static global::MyConfiguration InitializeMyConfiguration(IConfiguration configuration, BinderOptions? binderOptions)
{
if (configuration["Base"] is not string base)
{
throw new InvalidOperationException("Cannot create instance of type 'MyConfiguration' because parameter 'base' has no matching config. Each parameter in the constructor that does not have a default value must have a corresponding config entry.");
}
if (configuration["Event"] is not string event)
{
throw new InvalidOperationException("Cannot create instance of type 'MyConfiguration' because parameter 'event' has no matching config. Each parameter in the constructor that does not have a default value must have a corresponding config entry.");
}
return new global::MyConfiguration(base, event);
}
This causes confusing compiler errors.
Restore complete (1.8s)
ConfigBinderKeywordBindingRepro net10.0 failed with 5 error(s) (0.7s)
D:\Code\csharp\ConfigBinderKeywordBindingRepro\obj\Debug\net10.0\generated\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs(78,59): error CS0065: 'BindingExtensions.': event property must have both add and remove accessors
D:\Code\csharp\ConfigBinderKeywordBindingRepro\obj\Debug\net10.0\generated\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs(83,59): error CS0065: 'BindingExtensions.': event property must have both add and remove accessors
D:\Code\csharp\ConfigBinderKeywordBindingRepro\obj\Debug\net10.0\generated\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs(83,59): error CS0102: The type 'BindingExtensions' already contains a definition for ''
D:\Code\csharp\ConfigBinderKeywordBindingRepro\obj\Debug\net10.0\generated\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs(78,59): error CS0708: '': cannot declare instance members in a static class
D:\Code\csharp\ConfigBinderKeywordBindingRepro\obj\Debug\net10.0\generated\Microsoft.Extensions.Configuration.Binder.SourceGeneration\Microsoft.Extensions.Configuration.Binder.SourceGeneration.ConfigurationBindingGenerator\BindingExtensions.g.cs(83,59): error CS0708: '': cannot declare instance members in a static class
Build failed with 5 error(s) in 2.7s
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
I think the reason is probably similar to #130318 .
Both failed to process keyword identifiers.
Description
The Configuration.Binder source generator emits property and type names verbatim into identifier position without escaping C# keywords. If a configuration model has a property whose name is a keyword (declared with @, e.g.
@base,@event), the generated validator emits e.g.baseinstead of@base, which does not compile.Reproduction Steps
Expected behavior
The generated code compiles, emitting configuration.@base (or otherwise escaping keyword identifiers).
Actual behavior
Build fails. The generated BindingExtensions.g.cs contains (note the unescaped
baseandevent):This causes confusing compiler errors.
Regression?
No response
Known Workarounds
No response
Configuration
No response
Other information
I think the reason is probably similar to #130318 .
Both failed to process keyword identifiers.