Created
January 14, 2021 06:01
-
-
Save borland/3a8a0a8a56b3a4ef315e1f83f5ab4073 to your computer and use it in GitHub Desktop.
Experimental code for configuring an ASP.NET Core app using KDL rather than JSON
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// NOTE: This requires you to have a reference to KDL for .NET, and import the kdl-net namespace | |
// https://github.com/borland/kdl-net | |
// | |
// Highly experimental, but it works. | |
// | |
// NOTE: Once you have this code in your project, you can use | |
// | |
// var config = new ConfigurationBuilder() | |
// .AddKdlFile("appsettings.kdl", optional: false, reloadOnChange: false) | |
// | |
// in the same way you would for JSON | |
public static class KdlConfigurationExtensions | |
{ | |
public static IConfigurationBuilder AddKdlFile(this IConfigurationBuilder builder, string path, bool optional, bool reloadOnChange) | |
=> AddKdlFile(builder, null, path, optional, reloadOnChange); | |
public static IConfigurationBuilder AddKdlFile(this IConfigurationBuilder builder, IFileProvider provider, string path, bool optional, bool reloadOnChange) | |
{ | |
return builder.AddKdlFile(s => { | |
s.FileProvider = provider; | |
s.Path = path; | |
s.Optional = optional; | |
s.ReloadOnChange = reloadOnChange; | |
s.ResolveFileProvider(); | |
}); | |
} | |
public static IConfigurationBuilder AddKdlFile(this IConfigurationBuilder builder, Action<KdlConfigurationSource> configureSource) | |
=> builder.Add(configureSource); | |
class KdlConfigurationProvider : FileConfigurationProvider | |
{ | |
public KdlConfigurationProvider(KdlConfigurationSource source) : base(source) { } | |
public override void Load(Stream stream) | |
{ | |
try | |
{ | |
Data = KdlConfigurationFileParser.Parse(stream); | |
} | |
catch (KDLParseException e) | |
{ | |
throw new FormatException("Invalid KDL file", e); | |
} | |
} | |
} | |
public class KdlConfigurationSource : FileConfigurationSource | |
{ | |
public override IConfigurationProvider Build(IConfigurationBuilder builder) | |
{ | |
EnsureDefaults(builder); | |
return new KdlConfigurationProvider(this); | |
} | |
} | |
static class KdlConfigurationFileParser | |
{ | |
public static Dictionary<string, string> Parse(Stream stream) | |
{ | |
var doc = new KDLParser().Parse(stream); | |
var context = new Stack<string>(); | |
var result = new Dictionary<string, string>(); | |
VisitKdlDoc(doc, context, result); | |
return result; | |
} | |
public static void VisitKdlDoc(KDLDocument doc, Stack<string> context, Dictionary<string, string> result) | |
{ | |
foreach (var node in doc.Nodes) | |
{ | |
context.Push(node.Identifier); | |
if (node.Child != null) | |
{ | |
VisitKdlDoc(node.Child, context, result); | |
} | |
else if (node.Args.Count > 0) // we only support really basic trivial KDL of [key value] or key { subkey value }, nothing else fancier or multiple args, props etc | |
{ | |
result[string.Join(':', context)] = node.Args[0].AsString().Value; | |
} | |
context.Pop(); | |
} | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment