Ver Fonte

Fix to binary serialisation of object[].

Kenric Nugteren há 2 anos atrás
pai
commit
bdcbb6e09b
2 ficheiros alterados com 52 adições e 7 exclusões
  1. 33 4
      InABox.Core/Filter.cs
  2. 19 3
      InABox.Core/Serialization.cs

+ 33 - 4
InABox.Core/Filter.cs

@@ -1037,7 +1037,8 @@ namespace InABox.Core
             Guid,
             FilterConstant,
             Array,
-            SubQuery
+            SubQuery,
+            ObjectArray
         }
 
         private class ValueTypeClass
@@ -1071,8 +1072,17 @@ namespace InABox.Core
             {
                 // Essentially, the array ValueType will always be followed by another type which represents the element type; and if the element type is Array,
                 // it also will be followed by another ValueType.
-                valueType = ValueType.Array;
-                nestedType = type.GetElementType();
+                var elementType = type.GetElementType();
+
+                if(elementType == typeof(object) && writer.Settings.HandleFilterObjectArrays)
+                {
+                    valueType = ValueType.ObjectArray;
+                }
+                else
+                {
+                    nestedType = elementType;
+                    valueType = ValueType.Array;
+                }
             }
             else if (typeof(ISubQuery).IsAssignableFrom(type))
             {
@@ -1150,6 +1160,14 @@ namespace InABox.Core
             if (value is null)
             {
             }
+            else if(value is object[] objArr && writer.Settings.HandleFilterObjectArrays)
+            {
+                writer.Write(objArr.Length);
+                foreach (var item in objArr)
+                {
+                    SerializeValue(writer, item, true);
+                }
+            }
             else if (value.GetType().IsArray)
             {
                 var arr = (value as Array)!;
@@ -1278,6 +1296,8 @@ namespace InABox.Core
                     return ConvertToType(arrClass.ElementType)?.MakeArrayType();
                 case ValueType.SubQuery:
                     return typeof(ISubQuery);
+                case ValueType.ObjectArray:
+                    return typeof(object[]);
                 default:
                     throw new Exception($"Unknown value type {valueType.ValueType}");
             }
@@ -1312,9 +1332,18 @@ namespace InABox.Core
                     return reader.ReadGuid();
                 case ValueType.FilterConstant:
                     return (FilterConstant)reader.ReadInt32();
+                case ValueType.ObjectArray:
+                    var nItems = reader.ReadInt32();
+                    var objArr = new object?[nItems];
+                    for (int i = 0; i < nItems; ++i)
+                    {
+                        var elType = ReadValueType(reader);
+                        objArr[i] = DeserializeValue(reader, elType);
+                    }
+                    return objArr;
                 case ValueType.Array:
                     var array = (ArrayClass)valueType;
-                    var nItems = reader.ReadInt32();
+                    nItems = reader.ReadInt32();
                     var arr = Array.CreateInstance(ConvertToType(array.ElementType), nItems);
                     for (int i = 0; i < nItems; ++i)
                     {

+ 19 - 3
InABox.Core/Serialization.cs

@@ -267,21 +267,37 @@ namespace InABox.Core
         public bool IncludeNullables { get; set; }
         public string Version { get; set; }
 
-        public static BinarySerializationSettings Latest => V1_0;
+        /// <summary>
+        /// Handle correctly arrays of <see cref="object"/> inside of <see cref="Filter{T}.Value"/>.
+        /// </summary>
+        /// <remarks>
+        /// True in all serialisation versions >= 1.2.
+        /// </remarks>
+        public bool HandleFilterObjectArrays { get; set; }
+
+        public static BinarySerializationSettings Latest => V1_2;
 
         public static BinarySerializationSettings V1_0 = new BinarySerializationSettings("1.0")
         {
-            IncludeNullables = false
+            IncludeNullables = false,
+            HandleFilterObjectArrays = false
         };
         public static BinarySerializationSettings V1_1 = new BinarySerializationSettings("1.1")
         {
-            IncludeNullables = true
+            IncludeNullables = true,
+            HandleFilterObjectArrays = false
+        };
+        public static BinarySerializationSettings V1_2 = new BinarySerializationSettings("1.2")
+        {
+            IncludeNullables = true,
+            HandleFilterObjectArrays = true
         };
 
         public static BinarySerializationSettings ConvertVersionString(string version) => version switch
         {
             "1.0" => V1_0,
             "1.1" => V1_1,
+            "1.2" => V1_2,
             _ => V1_0
         };