Gnar.Enver.SourceGeneration
0.1.0-beta.3
dotnet add package Gnar.Enver.SourceGeneration --version 0.1.0-beta.3
NuGet\Install-Package Gnar.Enver.SourceGeneration -Version 0.1.0-beta.3
<PackageReference Include="Gnar.Enver.SourceGeneration" Version="0.1.0-beta.3" />
<PackageVersion Include="Gnar.Enver.SourceGeneration" Version="0.1.0-beta.3" />
<PackageReference Include="Gnar.Enver.SourceGeneration" />
paket add Gnar.Enver.SourceGeneration --version 0.1.0-beta.3
#r "nuget: Gnar.Enver.SourceGeneration, 0.1.0-beta.3"
#:package Gnar.Enver.SourceGeneration@0.1.0-beta.3
#addin nuget:?package=Gnar.Enver.SourceGeneration&version=0.1.0-beta.3&prerelease
#tool nuget:?package=Gnar.Enver.SourceGeneration&version=0.1.0-beta.3&prerelease
Enver.SourceGeneration
Attributes and a Roslyn source generator that bind .env values to
strongly-typed config classes.
Part of the Enver family. See the main project README for the broader ecosystem.
Quick start
dotnet add package Gnar.Enver.SourceGeneration
Mark a partial type with [EnverBindable] and the generator emits a
Bind family of static methods on it:
using Enver;
using Enver.SourceGeneration;
[EnverBindable]
public partial record DatabaseConfig(string Host, int Port)
{
public bool UseSsl { get; init; } = true;
}
// Pick one:
// 1. Bind by loading a .env from the app directory.
var cfg = DatabaseConfig.BindFromAppDirectory();
// 2. Bind by loading a .env from the working directory.
var cfg = DatabaseConfig.BindFromWorkingDirectory();
// 3. Bind by loading a specific file.
var cfg = DatabaseConfig.BindFromFile("/etc/myapp/.env");
// 4. Bind from an existing IEnvReader (EnvCollection, Environment.Variables,
// configuration.AsEnvReader(), …)
var cfg = DatabaseConfig.Bind(values);
By default, property names map to UPPER_SNAKE_CASE keys
(Host → HOST, UseSsl → USE_SSL).
Generated surface
For a self-bindable type ([EnverBindable] on the type itself), the generator
emits three static factories plus a streaming Binder:
public partial record DatabaseConfig
{
public static DatabaseConfig Bind(IEnvReader reader);
public static DatabaseConfig BindFromAppDirectory(
string fileName = ".env",
string? variant = null,
int maxAncestors = 0,
bool throwIfMissing = false,
EnvParseOptions parseOptions = default);
public static DatabaseConfig BindFromWorkingDirectory(
string fileName = ".env",
string? variant = null,
int maxAncestors = 0,
bool throwIfMissing = false,
EnvParseOptions parseOptions = default);
public static DatabaseConfig BindFromFile(
string path,
bool throwIfMissing = true,
EnvParseOptions parseOptions = default);
public sealed partial class Binder : EnvParser
{
public DatabaseConfig Build();
}
}
The same surface is generated on an external host ([EnverBindable<T>]),
with method names suffixed by the target's simple type name
(Configs.BindCacheConfig(...) / Configs.CacheConfigBinder). See
External host below.
Naming and prefix: [EnverConfig]
[EnverConfig] configures how member names map to keys. It does not
trigger generation on its own. Pair it with [EnverBindable] on the same
type:
[EnverBindable]
[EnverConfig("DB", KeyNaming = EnverKeyNamingConvention.UpperSnakeCase)]
public partial record DatabaseConfig(string Host, int Port);
// Reads DB_HOST and DB_PORT.
Naming conventions:
UpperSnakeCase(default):HostName→HOST_NAMESnakeCase:HostName→host_namePreserveOriginal:HostName→HostNameInherit: use the nearest enclosing[EnverConfig](falls back toUpperSnakeCase)
Prefixes and names set with [EnverKey] are not passed through
the KeyNaming convention.
Per-member overrides: [EnverKey]
[EnverBindable]
[EnverConfig("APP")]
public partial class AppConfig
{
// Map to APP_CUSTOM_NAME
[EnverKey("CUSTOM_NAME")]
public string Name { get; init; } = "";
// Map to GLOBAL_SETTING
[EnverKey(IgnorePrefix = true)]
public string GlobalSetting { get; init; } = "";
// Force optional
[EnverKey(Required = EnverRequirementBehavior.Optional)]
public int Port { get; init; }
// Force required
[EnverKey(Required = EnverRequirementBehavior.Required)]
public string? Tag { get; init; }
}
Records: when annotating a primary-constructor parameter, use the
[property: EnverKey(...)] target so the attribute lands on the generated
property rather than the parameter.
Other attributes
| Attribute | Effect |
|---|---|
[EnverIgnore] |
Skip a member that would otherwise be bound. |
[EnverUri(UriKind)] |
Specify UriKind for Uri members (default Absolute). |
[EnverFormatProvider(type, memberName)] |
Point at a static IFormatProvider member used when parsing numbers, dates, etc. Applies type-wide when placed on the class/struct; per-member when placed on a field/property. |
Required vs. optional
Each member is classified as required, optional, or with-default. The generator infers from C# signals, in order:
requiredmodifier → required- Nullable value or reference type → optional
- Property initializer → optional with default
- Non-nullable type → required
- Reference type under
#nullable disable→ optional
Required members that are missing throw EnverException at Bind() time
with the failing key. Optional members fall back to default(T) or the
declared initializer.
Override the inferred classification with
[EnverKey(Required = EnverRequirementBehavior.Required | .Optional)].
External host: [EnverBindable<T>]
Generate binders on a separate partial class:
public sealed record CacheConfig(int Ttl, string Region);
[EnverBindable<CacheConfig>]
public partial class Configs;
The static factories on the host are suffixed with the target's name, and the streaming binder lives alongside them:
var cfg = Configs.BindCacheConfig(reader);
var cfg = Configs.BindCacheConfigFromAppDirectory();
var binder = new Configs.CacheConfigBinder();
[EnverBindable<T>] is repeatable. One host can have binders for several targets.
Custom parsing
The generated Binder derives from EnvParser, so you can control parsing directly.
Binding directly to UTF-8 content:
var binder = new DatabaseConfig.Binder();
binder.Parse(
"""
HOST=db.internal
URL="postgres://${HOST}:5432"
"""u8
);
var cfg = binder.Build();
Supported types
string,bool,Guid,Uriint,long, and any numeric type implementingINumber<T>/IParsable<T>(including0x/0bprefix support)- Enums
- Any
IUtf8SpanParsable<T>,ISpanParsable<T>, orIParsable<T>(such asIPAddress,IPNetwork,Version)
See the main project README for the full list.
License
MIT.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Gnar.Enver (>= 0.1.0-beta.3)
-
net8.0
- Gnar.Enver (>= 0.1.0-beta.3)
-
net9.0
- Gnar.Enver (>= 0.1.0-beta.3)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|