From 88105794a997c181b721418cf23be703ef0b0cc5 Mon Sep 17 00:00:00 2001 From: Markus Ewald Date: Tue, 22 Jul 2014 11:10:14 +0000 Subject: [PATCH] The configuration file store now understands 'yes' and 'no' as booleans; implemented the Get() and TryGet() methods of the windows registry settings store git-svn-id: file:///srv/devel/repo-conversion/nusu@317 d2e56fa2-650e-0410-a79f-9358c0239efd --- .../Settings/ConfigurationFileStore.Test.cs | 21 +++++++++ Source/Settings/ConfigurationFileStore.cs | 18 +++++++- Source/Settings/WindowsRegistryStore.cs | 46 +++++++++++++++++-- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/Source/Settings/ConfigurationFileStore.Test.cs b/Source/Settings/ConfigurationFileStore.Test.cs index 5b1cb23..a096af1 100644 --- a/Source/Settings/ConfigurationFileStore.Test.cs +++ b/Source/Settings/ConfigurationFileStore.Test.cs @@ -401,6 +401,27 @@ namespace Nuclex.Support.Settings { Assert.That(() => load(fileContents), Throws.Exception); } + /// + /// Verifies that configuration files containing duplicate option names can not + /// be used with the configuration file store + /// + [ + Test, + TestCase("value = yes", true), + TestCase("value = true", true), + TestCase("value = no", false), + TestCase("value = false", false) + ] + public void BooleanLiteralsAreUnderstood(string fileContents, bool expectedValue) { + ConfigurationFileStore configurationFile = load(fileContents); + + if(expectedValue) { + Assert.That(configurationFile.Get(null, "value"), Is.True); + } else { + Assert.That(configurationFile.Get(null, "value"), Is.False); + } + } + /// Loads a configuration file from a string /// Contents of the configuration file /// The configuration file loaded from the string diff --git a/Source/Settings/ConfigurationFileStore.cs b/Source/Settings/ConfigurationFileStore.cs index cd96236..5481d1d 100644 --- a/Source/Settings/ConfigurationFileStore.cs +++ b/Source/Settings/ConfigurationFileStore.cs @@ -24,6 +24,8 @@ using System.Globalization; using System.IO; using System.Text; +using Nuclex.Support.Parsing; + namespace Nuclex.Support.Settings { /// Represents an ini- or cfg-like configuration file @@ -153,8 +155,20 @@ namespace Nuclex.Support.Settings { if(containingCategory != null) { Option option; if(containingCategory.OptionLookup.TryGetValue(optionName, out option)) { - value = (TValue)Convert.ChangeType(option.OptionValue.ToString(), typeof(TValue)); - return true; + if(typeof(TValue) == typeof(bool)) { + bool? boolean = ParserHelper.ParseBooleanLiteral(ref option.OptionValue); + if(boolean.HasValue) { + value = (TValue)(object)boolean.Value; + return true; + } else { + throw new FormatException( + "The value '" + option.OptionValue.ToString() + "' is not a boolean" + ); + } + } else { + value = (TValue)Convert.ChangeType(option.OptionValue.ToString(), typeof(TValue)); + return true; + } } } diff --git a/Source/Settings/WindowsRegistryStore.cs b/Source/Settings/WindowsRegistryStore.cs index 04e0567..560fd3d 100644 --- a/Source/Settings/WindowsRegistryStore.cs +++ b/Source/Settings/WindowsRegistryStore.cs @@ -22,8 +22,10 @@ License along with this library using System; using System.Collections.Generic; +using System.Globalization; using Microsoft.Win32; + using Nuclex.Support.Parsing; namespace Nuclex.Support.Settings { @@ -126,14 +128,11 @@ namespace Nuclex.Support.Settings { /// parameter, false otherwise /// public bool TryGet(string category, string optionName, out TValue value) { - throw new NotImplementedException(); if(string.IsNullOrEmpty(category)) { - object valueAsObject = this.rootKey.GetValue(optionName); - value = (TValue)Convert.ChangeType(valueAsObject, typeof(TValue)); + return tryGetValueFromKey(this.rootKey, optionName, out value); } else { using(RegistryKey categoryKey = this.rootKey.OpenSubKey(category, this.writable)) { - object valueAsObject = this.rootKey.GetValue(optionName); - value = (TValue)Convert.ChangeType(valueAsObject, typeof(TValue)); + return tryGetValueFromKey(this.rootKey, optionName, out value); } } } @@ -155,6 +154,43 @@ namespace Nuclex.Support.Settings { throw new NotImplementedException(); } + /// Tries to retrieve the value of a registry key if it exists + /// Type of value the registry key is expected to have + /// Registry key the value is stored under + /// Name of the option in the registry + /// Will receive the value read from the registry + /// True if the value was found, false otherwise + private bool tryGetValueFromKey( + RegistryKey categoryKey, string optionName, out TValue value + ) { + object valueAsObject = categoryKey.GetValue(optionName); + if(valueAsObject == null) { + value = default(TValue); + return false; + } + + if(typeof(TValue) == typeof(bool)) { + string valueAsString = (string)Convert.ChangeType( + valueAsObject, typeof(string), CultureInfo.InvariantCulture + ); + + bool? boolean = ParserHelper.ParseBooleanLiteral(valueAsString); + if(boolean.HasValue) { + value = (TValue)(object)boolean.Value; + return true; + } else { + throw new FormatException( + "The value '" + valueAsString + "' can not be intepreted as a boolean" + ); + } + } else { + value = (TValue)Convert.ChangeType( + valueAsObject, typeof(TValue), CultureInfo.InvariantCulture + ); + return true; + } + } + /// Figures out which .NET type best matches the registry value /// Registry key the key is stored in /// Name of the option that will be retrieved