π¦ KeyInject is a .NET library designed to inject values into configurations using regular expression patterns, with support for nested patterns.
βοΈ This facilitates dynamic and flexible configuration management in .NET applications.
π Configuration hot-reloads supported.
- π§© Features
- π Installation
- π Quick Start
- βοΈ Basic Configuration
- π Key Prefix
- π Patterns
- πͺ Nested patterns
- π Dependency Injection
- πͺ΅ Logging
- β Contribution
- Regex-Based Injection: Utilize regular expressions to identify and replace placeholders in your configuration files.
- Nested Pattern Support: Handle complex configurations with nested placeholders seamlessly.
- Easy Integration: Designed for straightforward integration into existing .NET projects.
- Supported versions:
net5.0and higher version supported
Install KeyInject using NuGet Package Manager:
Install-Package KeyInjectOr via the .NET CLI:
dotnet add package KeyInject
All versions can be found here.
Look at actual examples here ./examples;
In appsettings.json:
{
"ConnectionStrings": {
"Main": "server=${Database:Server};user=${DB_USER};password=${DB_PASSWORD}"
}
}In Environment variables:
DB_USER=addy DB_PASSWORD=greenlover
In user secrets:
{
"Database": {
"Server": "1.4.8.8"
}
}In Program.cs file:
using KeyInject; var builder = WebApplication.CreateBuilder(args); // Configuration order is up to you. // Remember, that ConfigurationProviders overrides each other! builder.Configuration.AddJsonFile("appsettings.json"); builder.Configuration.AddEnvironmentVariables(); // β Add Key Injection exactly at the latest position builder.Configuration.AddKeyInject(); // add services ... var app = builder.Build(); var conn = app.Configuration.GetConnectionString("Main"); await Console.Out.WriteLineAsync(conn); // β Output: server=1.4.8.8;user=addy;password=greenlover await app.RunAsync();
KeyInject always enriches from appsettings.json.
It's not neccessary to provide json configuration.
By default, ${_} pattern will be used if no other patterns provided.
(All the patterns will be described below)
{
"KeyInject": {
// simply enable or disable globally
"Enabled": true,
// allows to reload configuration if other Configuration Provides triggers OnReload()
"SetReloadEnabled": true,
// ignore case of pattern key group >> ${IgNore_Case_Of_thIs_woRD}
"IgnoreCase": true,
// set how many time config will be injected to resolve circular dependencies
"ReplaceRepeatCount": 10,
// from preset patterns ${_}, <<_>> ...
// if Patterns is empty, "${_}" pattern will be used anyway
"Patterns": [
"${_}", "{{_}}", "$<_>", "<<_>>", "!{_}!", "%_%"
],
// adding custom regex pattern.
// warn! must use ?<key> regex group, see documentation.
// no exception throw on bad regex.
"RegexPatterns": [
"!\\{(?<key>[^{}]+)\\}!"
],
// adding custom prefixes
"KeyPrefixes": [
"PRE_", "DATABASE_"
]
}
}
Extended configuration see in π Dependency Injection part.
Prefixes used to specify that we only want to replace keys starts with some value.
In example, for configured prefix DB_:
π« DATABASE_USER_PASSWORD - wont be replaced
β
DB_USER_PASSWORD - woill be replaced
π‘Notice!
If you specified prefixes, then only those patterns that start with this prefix will be replaced.
Can be registered with:
WebApplication.CreateBuilder(args) .Configuration.AddKeyInject(b => b .AddKeyPrefix("PRE_") .AddKeyPrefix("DATABASE_") );
Or with appsettings:
{
"KeyInject": {
"KeyPrefixes": [
"PRE_", "DATABASE_"
]
}
}π‘ Here is six default pattern names:
${_}
{{_}}
$<_>
<<_>>
!{_}!
%_%
Can be registered with:
WebApplication.CreateBuilder(args) .Configuration.AddKeyInject(b => b .AddPresetPattern("${_}") .AddPresetPattern("$<_>") );
Or with appsettings:
{
"KeyInject": {
"Patterns": [
"${_}", "{{_}}", "$<_>", "<<_>>", "!{_}!", "%_%"
]
}
}
β οΈ If no Pattern presented in explicit configuration will be used default:${_}
Their detailed description:
${_}
- regex:
\$\{(?<key>[^\{\}]+)\} - example:
${SOMEKEY},${some_key_2}
{{_}}
- regex:
\{\{(?<key>[^\{\}]+)\}\} - example:
{{SOMEKEY}},{{some_key_2}}
$<_>
- regex:
\$<(?<key>[^<>]+)> - example:
$<SOMEKEY>,$<some_key_2>
<<_>>
- regex:
<<(?<key>[^<>]+)>> - example:
<<SOMEKEY>>,<<some_key_2>>
!{_}!
- regex:
!\{(?<key>[^{}]+)\}! - example:
!{SOMEKEY}!,!{some_key_2}!
%_%
- regex:
%(?<key>[^%]+)% - example:
%SOMEKEY%,%some_key_2%
β οΈ Notice!
You must specify preset pattern name exactly in provided format!
Pattern names like"${...}"instead of${_}is not supported!
Of course, you can use multiple patterns at the same time.
You can use custom Regex patterns with builder or appsettings configuration.
You must to specify ?<key> regex group in pattern, like:
!\{(?<key>[^{}]+)\}!
β οΈ Group naming must be exactly:key
Custom pattern registration examples:
appsettings.json:
{
"KeyInject": {
"RegexPatterns": [
"!\\{(?<key>[^{}]+)\\}!"
]
}
}- with DI builder:
builder.Configuration.AddKeyInject(b => b // adding custom regex pattern. Warn! Must to use ?<key> regex group, see documentation. // no exception throw on bad regex. .AddRegexPattern(@"!\{(?<key>[^{}]+)\}!") // notice, adding built Regex CAN throw exception if regex text was incorrect .AddRegexPattern(new Regex(@"!\{(?<key>[^{}]+)\}!")) );
You can use nested patterns, by default supports 5 levels of nesting.
Here is an example of nesting:
- In
appsettings.json
{
"Connection": "${CONN}"
}- In Environment variable:
CONN="server=${DB_IP};user=${DB_USER};password=${DB_PASSWORD}"
- In Vault config provider (or some else provider too):
DB_IP=1.2.3.4 DB_USER=rootuser DB_PASSWORD=password123
- Result configuration string will be:
void DisplayConfig(IConfiguration config) { Console.WriteLine(config["Connection"]); // β Output: server=1.2.3.4;user=rootuser;password=password123 }
β οΈ Default supported nesting for5 levels, and it's enough for most cases.
You can change levels count with:
Configuration.AddKeyInject(b => b.SetReplaceRepeatCount(10) );
or in appsettings.json:
{
"KeyInject": {
"ReplaceRepeatCount": 10
}
}
β οΈ Warning!
Use.AddKeyInject()after other Configuration Provides!
Example:
var builder = WebApplication.CreateBuilder(args); // ... builder.Configuration.AddKeyInject(b => b // simply enable or disable globally .SetEnabled(true) // allows to reload configuration if other Configuration Provides triggers OnReload() .SetReloadEnabled(true) // adding custom prefixes .AddKeyPrefix("PRE_") .AddKeyPrefix("DATABASE_") // adding custom regex pattern. Warn! Must to use ?<key> regex group, see documentation. // no exception throw on bad regex. .AddRegexPattern(@"!\{(?<key>[^{}]+)\}!") // notice, adding built Regex CAN throw exception if regex text was incorrect .AddRegexPattern(new Regex(@"!\{(?<key>[^{}]+)\}!")) // from preset patterns ${_}, <<_>> ... .AddPresetPattern("${_}") // set how many time config will be injected to resolve circular dependencies .SetReplaceRepeatCount(10) // ignore case of pattern key group >> ${IgNore_Case_Of_thIs_woRD} .SetIgnoreCase(true) // choose yor custom config section instead default "KeyInject", first way: .EnrichFromAppSettings(builder.Configuration.GetSection("MyCustomSection")) // second way: .EnrichFromAppSettings(c => c.GetSection("MyCustomSection")) );
You can add logging to log configuration sources and replaced keys.
Simply pass ILoggerFactory, example:
var builder = WebApplication.CreateBuilder(args); // ... other config sources ... builder.Configuration.AddKeyInject(LoggerFactory.Create(b => b .SetMinimumLevel(LogLevel.Debug) .AddConsole() .AddDebug()) );
Console output example:
info: KeyInject.Injection.InjectionProcessor[0]
KeyInject starting process configuration
info: KeyInject.Injection.InjectionProcessor[0]
KeyInject configuration: {"Enabled":true,"ReplaceRepeatCount":5,"IgnoreCase":true,"KeyPrefixes":[],"RegexPatterns":["\\$\\{(?\u003Ckey\u003E[^\\{\\}]\u002B)\\}"]}
info: KeyInject.Injection.InjectionProcessor[0]
Found configuraion providers:
MemoryConfigurationProvider
EnvironmentVariablesConfigurationProvider Prefix: 'ASPNETCORE_'
EnvironmentVariablesConfigurationProvider Prefix: 'DOTNET_'
JsonConfigurationProvider for 'appsettings.json' (Optional)
JsonConfigurationProvider for 'appsettings.Development.json' (Optional)
EnvironmentVariablesConfigurationProvider
Microsoft.Extensions.Configuration.ChainedConfigurationProvider
JsonConfigurationProvider for 'appsettings.json' (Required)
info: KeyInject.Injection.InjectionProcessor[0]
For key [ConnectionStrings:Main] made [3] replacements
info: KeyInject.Injection.InjectionProcessor[0]
For key [ConnectionStrings:Some:Data:Key-3] made [1] replacements
info: KeyInject.Injection.InjectionProcessor[0]
Configuration loaded
π‘ The logging configuration is optional.
You don't have to passILoggerFactoryto theAddKeyInject(), just call without parameters if logging is not needed.
If you wanna to buy me a coffee π, I will be grateful for any tokens in TON network:
π noncommunicado.ton
π UQD0zFgp0p-eFnbL4cPA6DYqoeWzGbCA81KuU6BKwdFmf8jv