浏览代码

Re-added DeserializeInto

Kenric Nugteren 1 天之前
父节点
当前提交
2ae0773adc
共有 2 个文件被更改,包括 85 次插入10 次删除
  1. 81 6
      InABox.Core/Serialization.cs
  2. 4 4
      inabox.wpf/DynamicGrid/Editors/JsonEditor/JsonEditorControl.cs

+ 81 - 6
InABox.Core/Serialization.cs

@@ -6,6 +6,7 @@ using System.IO;
 using System.Linq;
 using System.Text.Json;
 using System.Text.Json.Serialization;
+using System.Text.Json.Serialization.Metadata;
 using InABox.Clients;
 
 namespace InABox.Core
@@ -43,15 +44,12 @@ namespace InABox.Core
             return _converters;
         }
 
-        private static JsonSerializerOptions SerializerSettings(bool indented = true)
+        private static JsonSerializerOptions SerializerSettings(bool indented = true, bool populateObject = false)
         {
-            var serializerSettings = CreateSerializerSettings();
-            serializerSettings.WriteIndented = indented;
-
-            return serializerSettings;
+            return CreateSerializerSettings(indented, populateObject);
         }
 
-        public static JsonSerializerOptions CreateSerializerSettings(bool indented = true)
+        public static JsonSerializerOptions CreateSerializerSettings(bool indented = true, bool populateObject = false)
         {
             var settings = new JsonSerializerOptions { };
 
@@ -59,6 +57,10 @@ namespace InABox.Core
             {
                 settings.Converters.Add(converter);
             }
+            if (populateObject)
+            {
+                settings.TypeInfoResolver = new PopulateTypeInfoResolver(new DefaultJsonTypeInfoResolver());
+            }
 
             settings.WriteIndented = indented;
             return settings;
@@ -149,6 +151,40 @@ namespace InABox.Core
             return ret;
         }
 
+        [return: MaybeNull]
+        public static void DeserializeInto<T>(string? json, T obj, bool strict = false)
+        {
+            if (string.IsNullOrWhiteSpace(json))
+                return;
+
+            try
+            {
+                var settings = SerializerSettings(populateObject: true);
+                PopulateTypeInfoResolver.t_populateObject = obj;
+                if (typeof(T).IsArray)
+                {
+                    JsonSerializer.Deserialize<T>(json, settings);
+                }
+                else
+                {
+                    JsonSerializer.Deserialize<T>(json, settings);
+                }
+            }
+            catch (Exception e)
+            {
+                if (strict)
+                {
+                    throw;
+                }
+
+                CoreUtils.LogException("", e);
+            }
+            finally
+            {
+                PopulateTypeInfoResolver.t_populateObject = null;
+            }
+        }
+
         public static object? Deserialize(Type T, string json) // where T : new()
         {
             var ret = T.GetDefault();
@@ -210,6 +246,45 @@ namespace InABox.Core
         #endregion
     }
 
+    internal class PopulateTypeInfoResolver : IJsonTypeInfoResolver
+    {
+        private readonly IJsonTypeInfoResolver? _jsonTypeInfoResolver;
+
+        [ThreadStatic]
+        internal static object? t_populateObject;
+
+        public PopulateTypeInfoResolver(IJsonTypeInfoResolver? jsonTypeInfoResolver)
+        {
+            _jsonTypeInfoResolver = jsonTypeInfoResolver;
+        }
+
+        public JsonTypeInfo? GetTypeInfo(Type type, JsonSerializerOptions options)
+        {
+            var typeInfo = _jsonTypeInfoResolver?.GetTypeInfo(type, options);
+            if(typeInfo != null && typeInfo.Kind != JsonTypeInfoKind.None)
+            {
+                var defaultCreateObject = typeInfo.CreateObject;
+                if(defaultCreateObject != null)
+                {
+                    typeInfo.CreateObject = () =>
+                    {
+                        if (t_populateObject != null)
+                        {
+                            var result = t_populateObject;
+                            t_populateObject = null;
+                            return result;
+                        }
+                        else
+                        {
+                            return defaultCreateObject.Invoke();
+                        }
+                    };
+                }
+            }
+            return typeInfo;
+        }
+    }
+
     public class CoreBinaryReader : BinaryReader
     {
         public BinarySerializationSettings Settings { get; set; }

+ 4 - 4
inabox.wpf/DynamicGrid/Editors/JsonEditor/JsonEditorControl.cs

@@ -59,7 +59,7 @@ internal class JsonEditorControl : DynamicEditorControl<string, JsonEditor>
         //DynamicEditorControlFactory.Register<JsonEditorControl, JsonEditor>();
     }
     
-    private Button _button;
+    private Button _button = null!; // Initialised in CreateEditor
 
     private string _value = "";
 
@@ -103,9 +103,9 @@ internal class JsonEditorControl : DynamicEditorControl<string, JsonEditor>
     {
         var type = (EditorDefinition as JsonEditor).Type;
         var listtype = typeof(List<>).MakeGenericType(type);
-        var list = Activator.CreateInstance(listtype) as IList;
-        if (!string.IsNullOrWhiteSpace(_value))
-            Serialization.DeserializeInto(_value, list);
+        var list = ((_value.IsNullOrWhiteSpace()
+            ? Activator.CreateInstance(listtype)
+            : Serialization.Deserialize(listtype, _value)) as IList)!;
 
         var array = new object[list.Count];
         list.CopyTo(array, 0);