Skip to content

Instantly share code, notes, and snippets.

@aopell
Last active May 7, 2021 13:30
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save aopell/fbb159cd6090cbb6dca861acc32476af to your computer and use it in GitHub Desktop.
Save aopell/fbb159cd6090cbb6dca861acc32476af to your computer and use it in GitHub Desktop.
C# JSON Settings Manager
using System;
using System.IO;
using System.Threading;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
namespace DiscordBotNew.Settings
{
public class SettingsManager
{
private string SettingsPath { get; }
private ReaderWriterLockSlim rwLock { get; }
private JObject settings;
public SettingsManager(string settingsPath)
{
rwLock = new ReaderWriterLockSlim();
SettingsPath = settingsPath;
LoadSettings();
}
/// <summary>
/// Creates a JSON file for settings at <see cref="SettingsPath"/>
/// </summary>
private void CreateSettingsFile()
{
try
{
if (!File.Exists(SettingsPath))
{
Directory.CreateDirectory(Path.GetDirectoryName(SettingsPath));
File.Create(SettingsPath).Dispose();
}
}
catch (Exception ex)
{
throw new FileNotFoundException($"The provided {nameof(SettingsPath)} was invalid", ex);
}
}
/// <summary>
/// Loads the contents of the settings file into <see cref="settings"/>
/// </summary>
private void LoadSettings()
{
if (settings == null)
{
using (new WriteLock(rwLock))
{
CreateSettingsFile();
string fileContents = File.ReadAllText(SettingsPath);
settings = string.IsNullOrWhiteSpace(fileContents) ? new JObject() : JObject.Parse(fileContents);
}
}
}
/// <summary>
/// Add a new setting or update existing setting with the same name
/// </summary>
/// <param name="setting">Setting name</param>
/// <param name="value">Setting value</param>
public void AddSetting(string setting, object value)
{
LoadSettings();
using (new WriteLock(rwLock))
{
if (settings[setting] == null && value != null)
settings.Add(setting, JToken.FromObject(value));
else if (value == null && settings[setting] != null)
settings[setting] = null;
else if (value != null)
settings[setting] = JToken.FromObject(value);
}
}
/// <summary>
/// Adds a batch of new settings, replacing already existing values with the same name
/// </summary>
/// <param name="settings"></param>
public void AddSettings(Dictionary<string, object> settings)
{
foreach (var setting in settings)
{
AddSetting(setting.Key, setting.Value);
}
}
/// <summary>
/// Gets the value of the setting with the provided name as type <c>T</c>
/// </summary>
/// <typeparam name="T">Result type</typeparam>
/// <param name="setting">Setting name</param>
/// <param name="result">Result value</param>
/// <returns>True when setting was successfully found, false when setting is not found</returns>
public bool GetSetting<T>(string setting, out T result)
{
result = default(T);
try
{
LoadSettings();
using (new ReadLock(rwLock))
{
if (settings[setting] == null) return false;
result = settings[setting].ToObject<T>();
}
return true;
}
catch (Exception ex)
{
try
{
using (new ReadLock(rwLock))
{
result = settings[setting].Value<T>();
}
return true;
}
catch (Exception ex2)
{
return false;
}
}
}
/// <summary>
/// Returns a dictionary of all settings
/// </summary>
/// <returns></returns>
public bool GetSettings(Dictionary<string, object> values) => GetSettings(out values);
/// <summary>
/// Returns a dictionary of all settings, where all settings are of the same type
/// </summary>
/// <typeparam name="TValue">The type of all of the settings</typeparam>
/// <returns></returns>
public bool GetSettings<TValue>(out Dictionary<string, TValue> values)
{
try
{
LoadSettings();
using (new ReadLock(rwLock))
{
values = settings.ToObject<Dictionary<string, TValue>>();
return true;
}
}
catch
{
values = null;
return false;
}
}
/// <summary>
/// Saves all queued settings to <see cref="SettingsPath"/>
/// </summary>
public void SaveSettings()
{
using (new WriteLock(rwLock))
{
File.WriteAllText(SettingsPath, settings.ToString(Formatting.Indented));
}
}
/// <summary>
/// Completely delete the settings file at <see cref="SettingsPath"/>. This action is irreversable.
/// </summary>
public void DeleteSettings()
{
using (new WriteLock(rwLock))
{
File.Delete(SettingsPath);
settings = null;
}
}
}
}
@goztrk
Copy link

goztrk commented Feb 14, 2019

What is this WriteLock() class? It seems it is not a .Net class?

@SpookyPool
Copy link

I want to know aswell what WriteLock() is.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment