Skip to content

About

Source generator that allows for managing (.NET MAUI) app configuration in appsettings.json, but then turns it into configuration classes with value-backed properties.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

20 Commits

Folders and files

Repository files navigation

BokWorks.AppConfigGenerator

A Roslyn source generator that parses appsettings.json files and emits strongly-typed static config classes with value-backed properties. Designed for .NET MAUI, but works with any .NET project.

No reflection. No runtime parsing. Just compile-time constants and read-only properties.

⚠️ This package is NOT intended for secrets or sensitive data. All values from appsettings.json are embedded as plain-text constants in your compiled assembly. Do not store API keys, passwords, connection strings with credentials, or any other sensitive information in these files.

This package simply makes environment-specific runtime configuration for .NET MAUI a bit easier, based on a setup that most C# developers are already familiar with from ASP.NET Core.

Getting Started

1. Install the package

dotnet add package BokWorks.AppConfigGenerator

Or via the Visual Studio NuGet Package Manager. The package is a development dependency — it won't ship with your app.

2. Add an appsettings.json to your project

{
  "Stage": "Prod",
  "MaxRetries": 3,
  "EnableLogging": true,
  "Api": {
    "BaseUrl": "https://api.example.com",
    "Timeout": 30
  }
}

That's it. On build, a static AppConfig class is generated automatically.

3. Use the generated class

    using MyApp.Config;

    var url = AppConfig.Api.BaseUrl;     // "https://api.example.com"
    var stage = AppConfig.Stage;         // "Prod"
    var retries = AppConfig.MaxRetries;  // 3L

You can also pass a nested config section as a whole — for example, to a method or constructor:

    using static MyApp.Config.AppConfig;

    // Pass the entire ApiConfig-section as an object
    var client = new ApiClient(ApiConfig);

The namespace is derived from your assembly name: {AssemblyName}.Config.

Generated Output

Given the JSON above, the generator emits:

    // <auto-generated/>
    namespace MyApp.Config
    {
        public static partial class AppConfig
        {
            public const string Stage = "Prod";
            public const long MaxRetries = 3L;
            public const bool EnableLogging = true;
            public static ApiConfig Api { get; } = new ApiConfig();

            public partial class ApiConfig
            {
                public string BaseUrl { get; } = "https://api.example.com";
                public long Timeout { get; } = 30L;
            }
        }
    }
  • Top-level primitives → const (inlined by the compiler, zero overhead)
  • Nested objects → partial class with read-only instance properties, exposed via a static property
  • All generated classes are partial — you can extend them in your own code (see Extending Generated Classes)

Local Override Files

For local development, you can override values using an environment-specific JSON file. These files are merged in Debug mode only and completely ignored in Release builds.

The following filenames are supported (in priority order):

File Priority
appsettings.Loc.json Highest
appsettings.Local.json
appsettings.Development.json Lowest

Only the highest-priority file found is used. Values from the local file are merged with appsettings.json, where appsettings.json wins on conflicts — the local file provides fallback/additional values.

Placeholder pattern

Use null values in appsettings.json as placeholders that get filled by the local file:

appsettings.json (committed to source control):

{
  "Stage": null,
  "Api": {
    "BaseUrl": null,
    "Timeout": 30
  }
}

appsettings.Loc.json (in .gitignore):

{
  "Stage": "Dev",
  "Api": {
    "BaseUrl": "https://localhost:5001"
  }
}

In Debug, the generator merges both files — null placeholders are filled by the local file. In Release, only appsettings.json is used, and null values are omitted from the generated class entirely.

Tip: Add your local override file to .gitignore so each developer can have their own settings without affecting the repository.

Extending Generated Classes

Since AppConfig and all nested config classes are partial, you can add computed properties:

    namespace MyApp.Config
    {
        public static partial class AppConfig
        {
            public partial class ApiConfig
            {
                public TimeSpan TimeoutSpan => TimeSpan.FromSeconds(Timeout);
            }
        }
    }

Usage: AppConfig.Api.TimeoutSpan

How It Works

The package ships as a Roslyn incremental source generator. On install it automatically:

  1. Registers appsettings.json (and local variants) as AdditionalFiles via an MSBuild .props file
  2. Makes the Configuration build property visible to the generator
  3. Parses and merges the JSON files at compile time
  4. Emits a strongly-typed AppConfig class as generated source

No manual .csproj edits required.

Type Mapping

JSON type C# type (top-level) C# type (nested)
"string" const string string { get; }
true / false const bool bool { get; }
123 (integer) const long long { get; }
1.5 (decimal) const double double { get; }
{ ... } (object) partial class + static property partial class + instance property
null Omitted (placeholder) Omitted (placeholder)

Diagnostics

ID Description
BWCFG001 Invalid JSON in a settings file

Requirements

  • Any .NET project that supports Roslyn source generators
  • No runtime dependencies

License

This project is licensed under the MIT License.

About

Source generator that allows for managing (.NET MAUI) app configuration in appsettings.json, but then turns it into configuration classes with value-backed properties.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages