You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

126 lines
3.6 KiB

  1. using IPA.Logging;
  2. using Newtonsoft.Json;
  3. using Newtonsoft.Json.Linq;
  4. using System;
  5. using System.Collections.Specialized;
  6. using System.ComponentModel;
  7. using System.IO;
  8. namespace IPA.Config.ConfigProviders
  9. {
  10. [Config.Type("json")]
  11. internal class JsonConfigProvider : IConfigProvider
  12. {
  13. public static void RegisterConfig()
  14. {
  15. Config.Register<JsonConfigProvider>();
  16. }
  17. private JObject jsonObj;
  18. #if NET4
  19. // TODO: create a wrapper that allows empty object creation
  20. public dynamic Dynamic => jsonObj;
  21. #endif
  22. public bool HasChanged { get; private set; }
  23. public bool InMemoryChanged { get; set; }
  24. public DateTime LastModified => File.GetLastWriteTime(Filename + ".json");
  25. private string _filename;
  26. public string Filename
  27. {
  28. get => _filename;
  29. set
  30. {
  31. if (_filename != null)
  32. throw new InvalidOperationException("Can only assign to Filename once");
  33. _filename = value;
  34. }
  35. }
  36. public void Load()
  37. {
  38. Logger.config.Debug($"Loading file {Filename}.json");
  39. var fileInfo = new FileInfo(Filename + ".json");
  40. if (fileInfo.Exists)
  41. {
  42. string json = File.ReadAllText(fileInfo.FullName);
  43. try
  44. {
  45. jsonObj = JObject.Parse(json);
  46. }
  47. catch (Exception e)
  48. {
  49. Logger.config.Error($"Error parsing JSON in file {Filename}.json; resetting to empty JSON");
  50. Logger.config.Error(e);
  51. jsonObj = new JObject();
  52. File.WriteAllText(fileInfo.FullName, JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
  53. }
  54. }
  55. else
  56. {
  57. jsonObj = new JObject();
  58. }
  59. SetupListeners();
  60. InMemoryChanged = true;
  61. }
  62. private void SetupListeners()
  63. {
  64. jsonObj.PropertyChanged += JsonObj_PropertyChanged;
  65. jsonObj.ListChanged += JsonObj_ListChanged;
  66. #if NET4
  67. jsonObj.CollectionChanged += JsonObj_CollectionChanged;
  68. #endif
  69. }
  70. #if NET4
  71. private void JsonObj_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
  72. {
  73. HasChanged = true;
  74. InMemoryChanged = true;
  75. }
  76. #endif
  77. private void JsonObj_ListChanged(object sender, ListChangedEventArgs e)
  78. {
  79. HasChanged = true;
  80. InMemoryChanged = true;
  81. }
  82. private void JsonObj_PropertyChanged(object sender, PropertyChangedEventArgs e)
  83. {
  84. HasChanged = true;
  85. InMemoryChanged = true;
  86. }
  87. public T Parse<T>()
  88. {
  89. if (jsonObj == null)
  90. return default(T);
  91. return jsonObj.ToObject<T>();
  92. }
  93. public void Save()
  94. {
  95. Logger.config.Debug($"Saving file {Filename}.json");
  96. if (!Directory.Exists(Path.GetDirectoryName(Filename)))
  97. Directory.CreateDirectory(Path.GetDirectoryName(Filename) ?? throw new InvalidOperationException());
  98. File.WriteAllText(Filename + ".json", JsonConvert.SerializeObject(jsonObj, Formatting.Indented));
  99. HasChanged = false;
  100. }
  101. public void Store<T>(T obj)
  102. {
  103. jsonObj = JObject.FromObject(obj);
  104. SetupListeners();
  105. HasChanged = true;
  106. InMemoryChanged = true;
  107. }
  108. }
  109. }