using System.Globalization;
using System.ComponentModel;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
public static void Main()
Environment.SetEnvironmentVariable("SomeSettings__ApiUrl", "set-via-env");
Environment.SetEnvironmentVariable("SomeSettings__Timeout", "10");
Environment.SetEnvironmentVariable("SomeSettings__ApiKey", "arn:api:key:name");
IConfiguration config = new ConfigurationBuilder()
.AddEnvironmentVariables()
var settings = new SomeSettings();
config.GetSection("SomeSettings").Bind(settings);
Handler(settings).Wait();
public static async Task Handler(SomeSettings settings)
Console.WriteLine($"ApiUrl: {settings.ApiUrl}");
Console.WriteLine($"Timeout: {settings.Timeout}");
var apiKey = await settings.ApiKey.Value;
Console.WriteLine($"ApiKey: {apiKey}");
public class SomeSettings {
public string ApiUrl { get; set; }
public int Timeout { get; set; }
public Secret ApiKey { get; set; }
[TypeConverter(typeof(SecretTypeConverter))]
public Task<string> Value { get; protected set; }
public Secret( string key ) {
Value = LookupSecretByKey(key);
protected Task<string> LookupSecretByKey(string key)
return Task.FromResult($"secret-value[{key}]");
public class SecretTypeConverter : TypeConverter
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
return sourceType == typeof(string) || base.CanConvertFrom(context, sourceType);
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
var casted = value as string;
: base.ConvertFrom(context, culture, value);