/*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