using Unosquare.Swan.Formatters;
using Unosquare.Swan.Reflection;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
namespace Unosquare.Swan.Abstractions {
///
/// Represents a provider to save and load settings using a plain JSON file.
///
///
/// The following example shows how to save and load settings.
///
/// using Unosquare.Swan.Abstractions;
///
/// public class Example
/// {
/// public static void Main()
/// {
/// // get user from settings
/// var user = SettingsProvider<Settings>.Instance.Global.User;
///
/// // modify the port
/// SettingsProvider<Settings>.Instance.Global.Port = 20;
///
/// // if we want these settings to persist
/// SettingsProvider<Settings>.Instance.PersistGlobalSettings();
/// }
///
/// public class Settings
/// {
/// public int Port { get; set; } = 9696;
///
/// public string User { get; set; } = "User";
/// }
/// }
///
///
/// The type of settings model.
public sealed class SettingsProvider
: SingletonBase> {
private readonly Object _syncRoot = new Object();
private T _global;
///
/// Gets or sets the configuration file path. By default the entry assembly directory is used
/// and the filename is 'appsettings.json'.
///
///
/// The configuration file path.
///
public String ConfigurationFilePath {
get; set;
} =
#if NETSTANDARD1_3
Path.Combine(Runtime.LocalStoragePath, "appsettings.json");
#else
Path.Combine(Runtime.EntryAssemblyDirectory, "appsettings.json");
#endif
///
/// Gets the global settings object.
///
///
/// The global settings object.
///
public T Global {
get {
lock(this._syncRoot) {
if(Equals(this._global, default(T))) {
this.ReloadGlobalSettings();
}
return this._global;
}
}
}
///
/// Reloads the global settings.
///
public void ReloadGlobalSettings() {
if(File.Exists(this.ConfigurationFilePath) == false || File.ReadAllText(this.ConfigurationFilePath).Length == 0) {
this.ResetGlobalSettings();
return;
}
lock(this._syncRoot) {
this._global = Json.Deserialize(File.ReadAllText(this.ConfigurationFilePath));
}
}
///
/// Persists the global settings.
///
public void PersistGlobalSettings() => File.WriteAllText(this.ConfigurationFilePath, Json.Serialize(this.Global, true));
///
/// Updates settings from list.
///
/// The list.
///
/// A list of settings of type ref="ExtendedPropertyInfo".
///
/// propertyList.
public List RefreshFromList(List> propertyList) {
if(propertyList == null) {
throw new ArgumentNullException(nameof(propertyList));
}
List changedSettings = new List();
IEnumerable globalProps = Runtime.PropertyTypeCache.RetrieveAllProperties();
foreach(ExtendedPropertyInfo property in propertyList) {
PropertyInfo propertyInfo = globalProps.FirstOrDefault(x => x.Name == property.Property);
if(propertyInfo == null) {
continue;
}
Object originalValue = propertyInfo.GetValue(this.Global);
Boolean isChanged = propertyInfo.PropertyType.IsArray
? property.Value is IEnumerable enumerable && propertyInfo.TrySetArray(enumerable.Cast