From fa767e5f3754b8c939b1f5a088d1c8e080f043ac Mon Sep 17 00:00:00 2001 From: bytewizer <58912473+bytewizer@users.noreply.github.com> Date: Sun, 28 Aug 2022 20:07:16 -0700 Subject: [PATCH] Added hosting configuration json and ini file support --- .github/workflows/actions.yml | 4 +- src/Bytewizer.TinyCLR.Runtime.sln | 12 ++ ...r.TinyCLR.Hosting.Configuration.Ini.csproj | 71 ++++++++++++ .../IniConfigurationExtensions.cs | 33 ++++++ .../IniStreamConfigurationProvider.cs | 97 ++++++++++++++++ .../IniStreamConfigurationSource.cs | 31 +++++ .../Properties/AssemblyInfo.cs | 4 + ....TinyCLR.Hosting.Configuration.Json.csproj | 79 +++++++++++++ .../FileConfigurationProvider.cs | 78 +++++++++++++ .../Configuration/FileConfigurationSource.cs | 44 +++++++ .../JsonConfigurationExtensions.cs | 62 ++++++++++ .../Configuration/JsonConfigurationParser.cs | 108 ++++++++++++++++++ .../JsonFileConfigurationProvider.cs | 30 +++++ .../JsonFileConfigurationSource.cs | 22 ++++ .../JsonStreamConfigurationProvider.cs | 30 +++++ .../JsonStreamConfigurationSource.cs | 22 ++++ .../Properties/AssemblyInfo.cs | 4 + ...wizer.TinyCLR.Hosting.Configuration.csproj | 8 -- .../Hosting/ConfigurationExtensions.cs | 25 +++- .../Bytewizer.TinyCLR.Logging.csproj | 4 - 20 files changed, 752 insertions(+), 16 deletions(-) create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Bytewizer.TinyCLR.Hosting.Configuration.Ini.csproj create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniConfigurationExtensions.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationProvider.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationSource.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Properties/AssemblyInfo.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Bytewizer.TinyCLR.Hosting.Configuration.Json.csproj create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationProvider.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationSource.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationExtensions.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationParser.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationProvider.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationSource.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationProvider.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationSource.cs create mode 100644 src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Properties/AssemblyInfo.cs diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml index 3efe69a..507ec1c 100644 --- a/.github/workflows/actions.yml +++ b/.github/workflows/actions.yml @@ -66,7 +66,7 @@ jobs: -p:PackageOutputPath=\builds\artifacts -p:BuildNumber="${{ steps.info.outputs.build }}" -p:Copyright="${{ steps.info.outputs.copyright }}" - -p:VersionPrefix="2.1.12" + -p:VersionPrefix="2.1.13" -p:VersionSuffix=preview.${{ steps.info.outputs.build }} -p:Configuration=${env:CONFIGURATION} -p:ContinuousIntegrationBuild=true @@ -78,7 +78,7 @@ jobs: -p:PackageOutputPath=\builds\artifacts -p:BuildNumber="${{ steps.info.outputs.build }}" -p:Copyright="${{ steps.info.outputs.copyright }}" - -p:VersionPrefix="2.1.12" + -p:VersionPrefix="2.1.13" -p:VersionSuffix=preview.${{ steps.info.outputs.build }} -p:Configuration=${env:CONFIGURATION} -p:ContinuousIntegrationBuild=true diff --git a/src/Bytewizer.TinyCLR.Runtime.sln b/src/Bytewizer.TinyCLR.Runtime.sln index a2a6069..97d7811 100644 --- a/src/Bytewizer.TinyCLR.Runtime.sln +++ b/src/Bytewizer.TinyCLR.Runtime.sln @@ -47,6 +47,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bytewizer.TinyCLR.Hosting", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bytewizer.TinyCLR.Hosting.Configuration", "hosting\Bytewizer.TinyCLR.Hosting.Configuration\Bytewizer.TinyCLR.Hosting.Configuration.csproj", "{71492D2D-6B78-46C8-9531-C02915742A46}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bytewizer.TinyCLR.Hosting.Configuration.Ini", "hosting\Bytewizer.TinyCLR.Hosting.Configuration.Ini\Bytewizer.TinyCLR.Hosting.Configuration.Ini.csproj", "{72592D2D-6B78-46C8-9531-C02915742A46}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bytewizer.TinyCLR.Hosting.Configuration.Json", "hosting\Bytewizer.TinyCLR.Hosting.Configuration.Json\Bytewizer.TinyCLR.Hosting.Configuration.Json.csproj", "{72492D2D-6B78-46C8-9531-C02915742A46}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -141,6 +145,14 @@ Global {71492D2D-6B78-46C8-9531-C02915742A46}.Debug|Any CPU.Build.0 = Debug|Any CPU {71492D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.ActiveCfg = Release|Any CPU {71492D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.Build.0 = Release|Any CPU + {72592D2D-6B78-46C8-9531-C02915742A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72592D2D-6B78-46C8-9531-C02915742A46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72592D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72592D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.Build.0 = Release|Any CPU + {72492D2D-6B78-46C8-9531-C02915742A46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {72492D2D-6B78-46C8-9531-C02915742A46}.Debug|Any CPU.Build.0 = Debug|Any CPU + {72492D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.ActiveCfg = Release|Any CPU + {72492D2D-6B78-46C8-9531-C02915742A46}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Bytewizer.TinyCLR.Hosting.Configuration.Ini.csproj b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Bytewizer.TinyCLR.Hosting.Configuration.Ini.csproj new file mode 100644 index 0000000..d6429db --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Bytewizer.TinyCLR.Hosting.Configuration.Ini.csproj @@ -0,0 +1,71 @@ + + + + + Debug + AnyCPU + {72592D2D-6B78-46C8-9531-C02915742A46} + Library + Properties + Bytewizer.TinyCLR.Hosting.Configuration.Ini + Bytewizer.TinyCLR.Hosting.Configuration.Ini + v4.8 + 512 + {A1948822-69DD-4150-919B-F3F42EFB71CC};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + 9 + + + + + + Generic Host extention library supporting ini files built for TinyCLR IoT devices. + ghi tinyclr tinyclros sitcore iot generic host hosting + TinyCLR + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + bin\Debug\Bytewizer.TinyCLR.Hosting.Configuration.Ini.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Bytewizer.TinyCLR.Hosting.Configuration.Ini.xml + + + + + + + + + + 2.2.0.4200 + + + 2.2.0.4200 + + + 6.3.0 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + {71492D2D-6B78-46C8-9531-C02915742A46} + Bytewizer.TinyCLR.Hosting.Configuration + + + + \ No newline at end of file diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniConfigurationExtensions.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniConfigurationExtensions.cs new file mode 100644 index 0000000..2d72c3a --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniConfigurationExtensions.cs @@ -0,0 +1,33 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Ini +{ + /// + /// Extension methods for adding . + /// + public static class IniConfigurationExtensions + { + /// + /// Adds a INI configuration source to . + /// + /// The to add to. + /// The to read the ini configuration data from. + /// The . + public static IConfigurationBuilder AddIniStream(this IConfigurationBuilder builder, Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException(); + } + + return builder.Add(new IniStreamConfigurationSource() { Stream = stream }); + } + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationProvider.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationProvider.cs new file mode 100644 index 0000000..c9d1378 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationProvider.cs @@ -0,0 +1,97 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; +using System.Collections; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Ini +{ + /// + /// An INI file based . + /// + public class IniStreamConfigurationProvider : StreamConfigurationProvider + { + /// + /// Constructor. + /// + /// The . + public IniStreamConfigurationProvider(IniStreamConfigurationSource source) : base(source) { } + + /// + /// Read a stream of INI values into a key/value dictionary. + /// + /// The stream of INI data. + /// The which was read from the stream. + public static Hashtable Read(Stream stream) + { + var data = new Hashtable(); + + using (var reader = new StreamReader(stream)) + { + string sectionPrefix = string.Empty; + + while (reader.Peek() != -1) + { + string rawLine = reader.ReadLine()!; // Since Peak didn't return -1, stream hasn't ended. + string line = rawLine.Trim(); + + // Ignore blank lines + //if (string.IsNullOrWhiteSpace(line)) + if (string.IsNullOrEmpty(line)) + { + continue; + } + // Ignore comments + if (line[0] is ';' or '#' or '/') + { + continue; + } + // [Section:header] + if (line[0] == '[' && line[line.Length - 1] == ']') + { + // remove the brackets + sectionPrefix = line.Substring(1, line.Length - 2).Trim() + ":"; + + continue; + } + + // key = value OR "value" + int separator = line.IndexOf('='); + if (separator < 0) + { + throw new FormatException(rawLine); + } + + string key = sectionPrefix + line.Substring(0, separator).Trim(); + string value = line.Substring(separator + 1).Trim(); + + // Remove quotes + if (value.Length > 1 && value[0] == '"' && value[value.Length - 1] == '"') + { + value = value.Substring(1, value.Length - 2); + } + + if (data.Contains(key)) + { + throw new FormatException(key); + } + + data[key.ToLower()] = value; + } + } + return data; + } + + /// + /// Loads INI configuration key/values from a stream into a provider. + /// + /// The to load ini configuration data from. + public override void Load(Stream stream) + { + Data = Read(stream); + } + } +} diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationSource.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationSource.cs new file mode 100644 index 0000000..e3cfcf3 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Configuration/IniStreamConfigurationSource.cs @@ -0,0 +1,31 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Ini +{ + /// + /// Represents an INI file as an . + /// Files are simple line structures (INI Files on Wikipedia) + /// + /// + /// [Section:Header] + /// key1=value1 + /// key2 = " value2 " + /// ; comment + /// # comment + /// / comment + /// + public class IniStreamConfigurationSource : StreamConfigurationSource + { + /// + /// Builds the for this source. + /// + /// The . + /// An + public override IConfigurationProvider Build(IConfigurationBuilder builder) + => new IniStreamConfigurationProvider(this); + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Properties/AssemblyInfo.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..391013c --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Ini/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System.Runtime.InteropServices; + +[assembly: ComVisible(false)] +[assembly: Guid("9e368003-1168-49f2-863e-8799a9436bea")] diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Bytewizer.TinyCLR.Hosting.Configuration.Json.csproj b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Bytewizer.TinyCLR.Hosting.Configuration.Json.csproj new file mode 100644 index 0000000..c21942e --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Bytewizer.TinyCLR.Hosting.Configuration.Json.csproj @@ -0,0 +1,79 @@ + + + + + Debug + AnyCPU + {72492D2D-6B78-46C8-9531-C02915742A46} + Library + Properties + Bytewizer.TinyCLR.Hosting.Configuration.Json + Bytewizer.TinyCLR.Hosting.Configuration.Json + v4.8 + 512 + {A1948822-69DD-4150-919B-F3F42EFB71CC};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb + 9 + + + + + + Generic Host extention library supporting json files built for TinyCLR IoT devices. + ghi tinyclr tinyclros sitcore iot generic host hosting + TinyCLR + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + bin\Debug\Bytewizer.TinyCLR.Hosting.Configuration.Json.xml + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + bin\Release\Bytewizer.TinyCLR.Hosting.Configuration.Json.xml + + + + + + + + + + + + + + + 2.2.0.4200 + + + 2.2.0.4200 + + + 2.2.0.4200 + + + 6.3.0 + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + {71492D2D-6B78-46C8-9531-C02915742A46} + Bytewizer.TinyCLR.Hosting.Configuration + + + + \ No newline at end of file diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationProvider.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationProvider.cs new file mode 100644 index 0000000..7442087 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationProvider.cs @@ -0,0 +1,78 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// File Stream based configuration provider. + /// + public abstract class FileConfigurationProvider : ConfigurationProvider + { + /// + /// The source settings for this provider. + /// + public FileConfigurationSource Source { get; } + + private bool _loaded; + + /// + /// Constructor. + /// + /// The source. + public FileConfigurationProvider(FileConfigurationSource source) + { + if (source == null) + { + throw new ArgumentNullException(); + } + + Source = source; + } + + /// + /// Generates a string representing this provider name and relevant details. + /// + /// The configuration name. + public override string ToString() + => $"{GetType().Name} for '{Source.Path}' ({(Source.Optional ? "optional" : "required")})"; + + /// + /// Load the configuration data from the stream. + /// + /// The data stream. + public abstract void Load(Stream stream); + + /// + /// Load the configuration data from the stream. Will throw after the first call. + /// + public override void Load() + { + if (_loaded) + { + throw new InvalidOperationException(); + } + + try + { + var filePath = $"{Source.DriveProvider.Name}{Source.Path}"; + Source.Stream = new FileStream(filePath, FileMode.Open, FileAccess.Read); + + Load(Source.Stream); + } + catch (Exception ex) + { + if (!Source.Optional) + { + throw ex; + } + } + + _loaded = true; + } + } +} diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationSource.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationSource.cs new file mode 100644 index 0000000..1433f32 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/FileConfigurationSource.cs @@ -0,0 +1,44 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System.IO; +using GHIElectronics.TinyCLR.IO; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// File based . + /// + public abstract class FileConfigurationSource : IConfigurationSource + { + /// + /// The stream containing the configuration data. + /// + public Stream Stream { get; set; } + + /// + /// The path to the file. + /// + public string Path { get; set; } + + /// + /// Determines if loading the file is optional. + /// + public bool Optional { get; set; } + + /// + /// The drive provider to the file. + /// + public IDriveProvider DriveProvider { get; set; } + + /// + /// Builds the for this source. + /// + /// The . + /// An + public abstract IConfigurationProvider Build(IConfigurationBuilder builder); + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationExtensions.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationExtensions.cs new file mode 100644 index 0000000..56f0946 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationExtensions.cs @@ -0,0 +1,62 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; + +using GHIElectronics.TinyCLR.IO; +using GHIElectronics.TinyCLR.Devices.Storage; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// Extension methods for adding . + /// + public static class JsonConfigurationExtensions + { + /// + /// Adds the JSON configuration provider at to . + /// + /// The to add to. + /// Path relative to the base path stored in + /// of . + /// Whether the file is optional. + /// The . + public static IConfigurationBuilder AddJsonFile(this IConfigurationBuilder builder, string path, bool optional) + { + if (builder == null) + { + throw new ArgumentNullException(); + } + + if (string.IsNullOrEmpty(path)) + { + throw new ArgumentNullException(); + } + + var controller = StorageController.GetDefault(); + var driveProvider = FileSystem.Mount(controller.Hdc); + + return builder.Add(new JsonFileConfigurationSource() + { Path = path, Optional = optional, DriveProvider = driveProvider }); + } + + /// + /// Adds a JSON configuration source to . + /// + /// The to add to. + /// The to read the json configuration data from. + /// The . + public static IConfigurationBuilder AddJsonStream(this IConfigurationBuilder builder, Stream stream) + { + if (stream == null) + { + throw new ArgumentNullException(); + } + + return builder.Add(new JsonStreamConfigurationSource() { Stream = stream }); + } + } +} diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationParser.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationParser.cs new file mode 100644 index 0000000..61e34ea --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonConfigurationParser.cs @@ -0,0 +1,108 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System; +using System.IO; +using System.Collections; +using System.Diagnostics; + +using GHIElectronics.TinyCLR.Data.Json; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + internal sealed class JsonConfigurationParser + { + private readonly Hashtable _data = new Hashtable(); + + public static Hashtable Parse(Stream input) + => new JsonConfigurationParser().ParseStream(input); + + private Hashtable ParseStream(Stream input) + { + try + { + JToken token = JsonConverter.Deserialize(input); + + if (token is JObject jobj) + { + foreach (JProperty member in jobj.Members) + { + foreach (DictionaryEntry pair in GetNode(member)) + { + _data.Add( + pair.Key.ToString().ToLower(), + pair.Value.ToString().Trim('"').TrimEnd('"') + ); + } + } + } + + if (token is JArray jarray) + { + for (int i = 0; i < jarray.Length; i++) + { + var property = new JProperty($"root{i}", jarray[i]); + + foreach (DictionaryEntry pair in GetNode(property)) + { + _data.Add( + pair.Key.ToString().ToLower(), + pair.Value.ToString().Trim('"').TrimEnd('"') + ); + } + } + } + } + catch + { + throw new FormatException("Could not parse the JSON file."); + } + + return _data; + } + + private static ArrayList GetNode(JProperty node) + { + var items = new ArrayList(); + + if (node.Value is JObject jobj) + { + foreach (JProperty member in jobj.Members) + { + var key = string.Concat(node.Name, ":", member.Name); + var values = GetNode(new JProperty(key, member.Value)); + + foreach (DictionaryEntry pair in values) + { + items.Add(pair); + } + } + + return items; + } + + if (node.Value is JArray jarray) + { + for (int i = 0; i < jarray.Length; i++) + { + var key = string.Concat(node.Name, ":", i); + var values = GetNode(new JProperty(key, jarray[i])); + + foreach (DictionaryEntry pair in values) + { + items.Add(pair); + } + } + + return items; + } + + items.Add(new DictionaryEntry (node.Name, node.Value)); + + return items; + } + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationProvider.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationProvider.cs new file mode 100644 index 0000000..9c0d8eb --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationProvider.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System.IO; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// Loads configuration key/values from a json file stream into a provider. + /// + public class JsonFileConfigurationProvider : FileConfigurationProvider + { + /// + /// Constructor. + /// + /// The . + public JsonFileConfigurationProvider(JsonFileConfigurationSource source) : base(source) { } + + /// + /// Loads json configuration key/values from a stream into a provider. + /// + /// The json to load configuration data from. + public override void Load(Stream stream) + { + Data = JsonConfigurationParser.Parse(stream); + } + } +} diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationSource.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationSource.cs new file mode 100644 index 0000000..e8b90f3 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonFileConfigurationSource.cs @@ -0,0 +1,22 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// Represents a JSON file as an . + /// + public class JsonFileConfigurationSource : FileConfigurationSource + { + /// + /// Builds the for this source. + /// + /// The . + /// An + public override IConfigurationProvider Build(IConfigurationBuilder builder) + => new JsonFileConfigurationProvider(this); + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationProvider.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationProvider.cs new file mode 100644 index 0000000..3c43405 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationProvider.cs @@ -0,0 +1,30 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +using System.IO; + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// Loads configuration key/values from a json stream into a provider. + /// + public class JsonStreamConfigurationProvider : StreamConfigurationProvider + { + /// + /// Constructor. + /// + /// The . + public JsonStreamConfigurationProvider(JsonStreamConfigurationSource source) : base(source) { } + + /// + /// Loads json configuration key/values from a stream into a provider. + /// + /// The json to load configuration data from. + public override void Load(Stream stream) + { + Data = JsonConfigurationParser.Parse(stream); + } + } +} diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationSource.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationSource.cs new file mode 100644 index 0000000..f957240 --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Configuration/JsonStreamConfigurationSource.cs @@ -0,0 +1,22 @@ +// +// Copyright (c) .NET Foundation and Contributors +// See LICENSE file in the project root for full license information. +// + +namespace Bytewizer.TinyCLR.Hosting.Configuration.Json +{ + /// + /// Represents a JSON file as an . + /// + public class JsonStreamConfigurationSource : StreamConfigurationSource + { + /// + /// Builds the for this source. + /// + /// The . + /// An + public override IConfigurationProvider Build(IConfigurationBuilder builder) + => new JsonStreamConfigurationProvider(this); + } +} + diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Properties/AssemblyInfo.cs b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..391013c --- /dev/null +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration.Json/Properties/AssemblyInfo.cs @@ -0,0 +1,4 @@ +using System.Runtime.InteropServices; + +[assembly: ComVisible(false)] +[assembly: Guid("9e368003-1168-49f2-863e-8799a9436bea")] diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration/Bytewizer.TinyCLR.Hosting.Configuration.csproj b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration/Bytewizer.TinyCLR.Hosting.Configuration.csproj index 2ea24c7..a5cfeec 100644 --- a/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration/Bytewizer.TinyCLR.Hosting.Configuration.csproj +++ b/src/hosting/Bytewizer.TinyCLR.Hosting.Configuration/Bytewizer.TinyCLR.Hosting.Configuration.csproj @@ -70,18 +70,10 @@ - - {70392D1D-6B78-46C8-9531-C02915742A46} - Bytewizer.TinyCLR.Core - {F5997E37-7348-4FA6-9103-990D9906DA4F} Bytewizer.TinyCLR.DependencyInjection.Abstractions - - {AEB62F01-BA5F-45E3-A82C-4D2E058046A3} - Bytewizer.TinyCLR.DependencyInjection - {70492D2D-6B78-46C8-9531-C02915742A46} Bytewizer.TinyCLR.Hosting diff --git a/src/hosting/Bytewizer.TinyCLR.Hosting/Hosting/ConfigurationExtensions.cs b/src/hosting/Bytewizer.TinyCLR.Hosting/Hosting/ConfigurationExtensions.cs index 476ff64..46525b3 100644 --- a/src/hosting/Bytewizer.TinyCLR.Hosting/Hosting/ConfigurationExtensions.cs +++ b/src/hosting/Bytewizer.TinyCLR.Hosting/Hosting/ConfigurationExtensions.cs @@ -57,8 +57,9 @@ public static object GetOrDefault(this IConfiguration configuration, string key, } var type = defaultValue.GetType(); + if (type == typeof(string)) return (string)value; - //if (type == typeof(bool)) return ((string)value).ToLower() == "true"; + if (type == typeof(bool)) return ((string)value).ToBoolean(); if (type == typeof(int)) return int.Parse((string)value); if (type == typeof(uint)) return uint.Parse((string)value); if (type == typeof(byte)) return byte.Parse((string)value); @@ -68,8 +69,28 @@ public static object GetOrDefault(this IConfiguration configuration, string key, if (type == typeof(long)) return long.Parse((string)value); if (type == typeof(ulong)) return ulong.Parse((string)value); if (type == typeof(double)) return double.Parse((string)value); - + return value; } } + + internal static class StringExtensions + { + public static bool ToBoolean(this string value) + { + switch (value.ToLower().Trim()) + { + case "true": + return true; + case "1": + return true; + case "false": + return false; + case "0": + return false; + default: + return false; + } + } + } } diff --git a/src/logging/Bytewizer.TinyCLR.Logging/Bytewizer.TinyCLR.Logging.csproj b/src/logging/Bytewizer.TinyCLR.Logging/Bytewizer.TinyCLR.Logging.csproj index 26271d9..87e90d0 100644 --- a/src/logging/Bytewizer.TinyCLR.Logging/Bytewizer.TinyCLR.Logging.csproj +++ b/src/logging/Bytewizer.TinyCLR.Logging/Bytewizer.TinyCLR.Logging.csproj @@ -75,10 +75,6 @@ {F5997E37-7348-4FA6-9103-990D9906DA4F} Bytewizer.TinyCLR.DependencyInjection.Abstractions - - {AEB62F01-BA5F-45E3-A82C-4D2E058046A3} - Bytewizer.TinyCLR.DependencyInjection - {598D7917-49D1-4E76-BFF4-23221BAD7072} Bytewizer.TinyCLR.Logging.Abstractions