/*using System; using System.Reflection; using System.Collections.Concurrent; using Config.Net.TypeParsers; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; namespace Config.Net { /// /// Generic container for test settings /// public abstract class SettingsContainer { private readonly IConfigConfiguration _config = new ContainerConfiguration(); private readonly ConcurrentDictionary _nameToOption = new ConcurrentDictionary(); private readonly ConcurrentDictionary _nameToOptionValue = new ConcurrentDictionary(); private static readonly DefaultParser DefaultParser = new DefaultParser(); private readonly string _namespace; private bool _isConfigured; /// /// Constructs the container in default namespace /// protected SettingsContainer() : this(null) { } /// /// Constructs the container allowing to specify a custom namespace /// /// protected SettingsContainer(string namespaceName) { _namespace = namespaceName; DiscoverProperties(); } /// /// Reads the option value /// /// Option type /// Option reference /// Option value public T Read(Option option) { CheckConfigured(); CheckCanParse(option.NonNullableType); OptionValue optionValue; _nameToOptionValue.TryGetValue(option.Name, out optionValue); if (!optionValue.IsExpired(_config.CacheTimeout)) { return (T) optionValue.RawValue; } string value = ReadFirstValue(option.Name); if (value == null) { optionValue.RawValue = option.DefaultValue; } else if (DefaultParser.IsSupported(option.NonNullableType)) { object resultObject; if (DefaultParser.TryParse(value, option.NonNullableType, out resultObject)) { optionValue.Update((T) resultObject); } else { optionValue.Update(option.DefaultValue); } } else { ITypeParser typeParser = _config.GetParser(option.NonNullableType); object result; typeParser.TryParse(value, option.NonNullableType, out result); optionValue.Update((T) result); } OnReadOption(option, optionValue.RawValue); return (T) optionValue.RawValue; } /// /// Writes a new value to the option /// /// Option type /// Option reference /// New value public void Write(Option option, T value) { CheckConfigured(); CheckCanParse(option.NonNullableType); OptionValue optionValue; _nameToOptionValue.TryGetValue(option.Name, out optionValue); foreach (IConfigStore store in _config.Stores) { if (store.CanWrite) { string rawValue = AreEqual(value, option.DefaultValue) ? null : GetRawStringValue(option, value); store.Write(option.Name, rawValue); break; } } optionValue.Update(value); OnWriteOption(option, value); } /// /// This method is called internally before containers is ready for use. You can specify /// configuration stores or any other options here. /// /// protected abstract void OnConfigure(IConfigConfiguration configuration); /// /// Called after any value is read /// /// Optiond that is read /// Option value read from a store protected virtual void OnReadOption(Option option, object value) { } /// /// Called before any value is written /// /// Option that is written /// Option value to write protected virtual void OnWriteOption(Option option, object value) { } private void CheckConfigured() { if (_isConfigured) return; OnConfigure(_config); _isConfigured = true; } [Ignore] private void DiscoverProperties() { Type t = this.GetType(); Type optionType = typeof(Option); IEnumerable properties = t.GetRuntimeProperties() .Where(f => f.PropertyType.GetTypeInfo().IsSubclassOf(optionType) && f.GetCustomAttribute() == null).ToList(); // Only include fields that have not already been added as properties IEnumerable fields = t.GetRuntimeFields() .Where(f => f.IsPublic && f.FieldType.GetTypeInfo().IsSubclassOf(optionType)).ToList(); foreach (PropertyInfo pi in properties) { AssignOption(pi.GetValue(this), pi, pi.PropertyType.GetTypeInfo(), pi.CanWrite, v => pi.SetValue(this, v)); } foreach (FieldInfo fi in fields) { if (properties.Any(p => p.Name == fi.Name)) throw new ArgumentException( $"Field '{fi.Name}' has already been defined as a property."); var methInfo = fi.FieldType.GetTypeInfo(); if (!methInfo.IsSubclassOf(optionType)) continue; AssignOption(fi.GetValue(this), fi, methInfo, true, v => fi.SetValue(this, v)); } } private void AssignOption(object objValue, MemberInfo pi, TypeInfo propInfo, bool writeable, Action setter) { { //check if it has the value if (objValue == null) { // Throw an exception if it's impossible to assign a default value to a read-only property with no default object assigned if (!writeable) throw new ArgumentException( $"Property/Field '{pi.Name}' must either be settable or be pre-initialised with an Option<> object as a property, or marked as readonly if a field"); //create default instance if it doesn't exist var nt = typeof(Option<>); Type[] ntArgs = propInfo.GetGenericArguments(); Type ntGen = nt.MakeGenericType(ntArgs); objValue = Activator.CreateInstance(ntGen); //set the instance value back to the container setter(objValue); } Option value = (Option) objValue; if (string.IsNullOrEmpty(value.Name)) value.Name = pi.Name; value.Name = GetFullKeyName(value.Name); value._parent = this; value.NonNullableType = Nullable.GetUnderlyingType(value.ValueType); value.IsNullable = value.NonNullableType != null; if (value.NonNullableType == null) value.NonNullableType = value.ValueType; _nameToOption[value.Name] = value; _nameToOptionValue[value.Name] = new OptionValue(); } } private string GetFullKeyName(string name) { if (string.IsNullOrEmpty(_namespace)) return name; return _namespace + "." + name; } private bool CanParse(Type t) { return _config.HasParser(t) || DefaultParser.IsSupported(t); } private string ReadFirstValue(string key) { foreach (IConfigStore store in _config.Stores) { if (store.CanRead) { string value = store.Read(key); if (value != null) return value; } } return null; } private void CheckCanParse(Type t) { if (!CanParse(t)) { throw new ArgumentException("value parser for " + t.FullName + " is not registered and not supported by default parser"); } } private bool AreEqual(object value1, object value2) { if (value1 == null && value2 == null) return true; if (value1 != null && value2 != null) { Type t1 = value1.GetType(); Type t2 = value2.GetType(); if (t1.IsArray && t2.IsArray) { return AreEqual((Array) value1, (Array) value2); } } return value1 != null && value1.Equals(value2); } private bool AreEqual(Array a, Array b) { if (a == null && b == null) return true; if (a == null || b == null) return false; if (a.Length != b.Length) return false; for (int i = 0; i < a.Length; i++) { object obj1 = a.GetValue(i); object obj2 = b.GetValue(i); if (!AreEqual(obj1, obj2)) return false; } return true; } private string GetRawStringValue(Option option, T value) { string stringValue = null; ITypeParser typeParser = _config.GetParser(option.NonNullableType); if (typeParser != null) { stringValue = typeParser.ToRawString(value); } else { if (DefaultParser.IsSupported(typeof(T))) { stringValue = DefaultParser.ToRawString(value); } } return stringValue; } } }*/