Selaa lähdekoodia

Added Serialisation version settings, including a nullable flag.

Kenric Nugteren 2 vuotta sitten
vanhempi
commit
1582291398

+ 14 - 11
InABox.Client.Remote.Json/JsonClient.cs

@@ -34,16 +34,19 @@ namespace InABox.Clients
     {
         private readonly bool _compression = true;
 
-        public JsonClient(string url, int port, bool useSimpleEncryption, bool compression) : base(url, port, useSimpleEncryption)
+        private BinarySerializationSettings BinarySerializationSettings;
+
+        public JsonClient(string url, int port, bool useSimpleEncryption, bool compression, BinarySerializationSettings binarySerializationSettings) : base(url, port, useSimpleEncryption)
         {
             _compression = compression;
+            BinarySerializationSettings = binarySerializationSettings;
         }
 
-        public JsonClient(string url, int port, bool useSimpleEncryption) : this(url, port, useSimpleEncryption, true)
+        public JsonClient(string url, int port, bool useSimpleEncryption) : this(url, port, useSimpleEncryption, true, BinarySerializationSettings.Latest)
         {
         }
 
-        public JsonClient(string url, int port) : this(url, port, false, true)
+        public JsonClient(string url, int port) : this(url, port, false, true, BinarySerializationSettings.Latest)
         {
         }
 
@@ -71,7 +74,6 @@ namespace InABox.Clients
             //CheckSecuritySettings();
 
             var result = default(TResponse);
-            long length = 0;
 
             if (string.IsNullOrEmpty(URL))
             {
@@ -89,11 +91,12 @@ namespace InABox.Clients
             var uri = new Uri(string.Format("{0}:{1}", URL, Port));
             var cli = new RestClient(uri);
             var cmd = string.Format(
-                "{0}{1}?format={2}&responseFormat={3}", 
+                "{0}{1}?format={2}&responseFormat={3}&serializationVersion={4}", 
                 Action, 
                 includeEntity ? typeof(TEntity).Name : "",
                 requestFormat,
-                responseFormat
+                responseFormat,
+                BinarySerializationSettings.Version
             );
             var req = new RestRequest(cmd, Method.POST)
             {
@@ -111,7 +114,7 @@ namespace InABox.Clients
                 {
                     if (responseFormat == SerializationFormat.Binary && typeof(TResponse).HasInterface<ISerializeBinary>())
                     {
-                        result = (TResponse)Serialization.ReadBinary(typeof(TResponse), stream);
+                        result = (TResponse)Serialization.ReadBinary(typeof(TResponse), stream, BinarySerializationSettings);
                     }
                     else
                     {
@@ -127,7 +130,7 @@ namespace InABox.Clients
 
             if(requestFormat == SerializationFormat.Binary && request is ISerializeBinary binary)
             {
-                var data = binary.WriteBinary();
+                var data = binary.WriteBinary(BinarySerializationSettings);
 
                 req.AddOrUpdateParameter("application/octet-stream", data, ParameterType.RequestBody);
                 req.RequestFormat = DataFormat.None;
@@ -175,7 +178,7 @@ namespace InABox.Clients
 
                             if (responseFormat == SerializationFormat.Binary && typeof(TResponse).HasInterface<ISerializeBinary>())
                             {
-                                result = (TResponse)Serialization.ReadBinary(typeof(TResponse), stream);
+                                result = (TResponse)Serialization.ReadBinary(typeof(TResponse), stream, BinarySerializationSettings);
                             }
                             else
                             {
@@ -235,7 +238,7 @@ namespace InABox.Clients
                     }
                 }
             }
-            catch (Exception e)
+            catch (Exception)
             {
             }
 
@@ -299,7 +302,7 @@ namespace InABox.Clients
                     return info.Info;
                 }
             }
-            catch (Exception e)
+            catch (Exception)
             {
                 return new DatabaseInfo();
             }

+ 2 - 2
InABox.Client.Remote.Shared/RemoteClient.cs

@@ -290,7 +290,7 @@ namespace InABox.Clients
 
             PrepareRequest(request);
 
-            var response = SendRequest<SaveRequest<TEntity>, SaveResponse<TEntity>>(request, "Save", SerializationFormat.Json, SerializationFormat.Json);
+            var response = SendRequest<SaveRequest<TEntity>, SaveResponse<TEntity>>(request, "Save", SerializationFormat.Binary, SerializationFormat.Json);
             switch (response.Status)
             {
                 case StatusCode.OK:
@@ -334,7 +334,7 @@ namespace InABox.Clients
 
             PrepareRequest(request);
 
-            var response = SendRequest<MultiSaveRequest<TEntity>, MultiSaveResponse<TEntity>>(request, "MultiSave", SerializationFormat.Json, SerializationFormat.Json);
+            var response = SendRequest<MultiSaveRequest<TEntity>, MultiSaveResponse<TEntity>>(request, "MultiSave", SerializationFormat.Binary, SerializationFormat.Json);
             switch (response.Status)
             {
                 case StatusCode.OK:

+ 14 - 14
InABox.Core/Client/Request.cs

@@ -17,7 +17,7 @@ namespace InABox.Clients
         public string Version { get; set; }
         public Guid Session { get; set; }
 
-        public void SerializeBinary(BinaryWriter writer)
+        public void SerializeBinary(CoreBinaryWriter writer)
         {
             writer.Write(UserID ?? "");
             writer.Write(Password ?? "");
@@ -26,7 +26,7 @@ namespace InABox.Clients
             writer.Write(Session);
         }
 
-        public void DeserializeBinary(BinaryReader reader)
+        public void DeserializeBinary(CoreBinaryReader reader)
         {
             UserID = reader.ReadString();
             Password = reader.ReadString();
@@ -49,12 +49,12 @@ namespace InABox.Clients
 
         public abstract RequestMethod GetMethod();
 
-        public virtual void SerializeBinary(BinaryWriter writer)
+        public virtual void SerializeBinary(CoreBinaryWriter writer)
         {
             Credentials.SerializeBinary(writer);
         }
 
-        public virtual void DeserializeBinary(BinaryReader reader)
+        public virtual void DeserializeBinary(CoreBinaryReader reader)
         {
             Credentials.DeserializeBinary(reader);
         }
@@ -96,7 +96,7 @@ namespace InABox.Clients
 
         public List<string> Messages { get; }
 
-        public virtual void DeserializeBinary(BinaryReader reader)
+        public virtual void DeserializeBinary(CoreBinaryReader reader)
         {
             Status = (StatusCode)Enum.ToObject(typeof(StatusCode), reader.ReadInt32());
             Messages.Clear();
@@ -107,7 +107,7 @@ namespace InABox.Clients
             }
         }
 
-        public virtual void SerializeBinary(BinaryWriter writer)
+        public virtual void SerializeBinary(CoreBinaryWriter writer)
         {
             writer.Write((int)Status);
 
@@ -158,7 +158,7 @@ namespace InABox.Clients
     {
         public CoreTable? Items { get; set; }
 
-        public override void DeserializeBinary(BinaryReader reader)
+        public override void DeserializeBinary(CoreBinaryReader reader)
         {
             base.DeserializeBinary(reader);
 
@@ -173,7 +173,7 @@ namespace InABox.Clients
             }
         }
 
-        public override void SerializeBinary(BinaryWriter writer)
+        public override void SerializeBinary(CoreBinaryWriter writer)
         {
             base.SerializeBinary(writer);
 
@@ -212,7 +212,7 @@ namespace InABox.Clients
 
         public override RequestMethod GetMethod() => RequestMethod.MultiSave;
 
-        public override void SerializeBinary(BinaryWriter writer)
+        public override void SerializeBinary(CoreBinaryWriter writer)
         {
             base.SerializeBinary(writer);
 
@@ -221,7 +221,7 @@ namespace InABox.Clients
             writer.Write(ReturnOnlyChanged);
         }
 
-        public override void DeserializeBinary(BinaryReader reader)
+        public override void DeserializeBinary(CoreBinaryReader reader)
         {
             base.DeserializeBinary(reader);
 
@@ -248,7 +248,7 @@ namespace InABox.Clients
 
         public override RequestMethod GetMethod() => RequestMethod.Save;
 
-        public override void SerializeBinary(BinaryWriter writer)
+        public override void SerializeBinary(CoreBinaryWriter writer)
         {
             base.SerializeBinary(writer);
 
@@ -257,7 +257,7 @@ namespace InABox.Clients
             writer.Write(ReturnOnlyChanged);
         }
 
-        public override void DeserializeBinary(BinaryReader reader)
+        public override void DeserializeBinary(CoreBinaryReader reader)
         {
             base.DeserializeBinary(reader);
 
@@ -318,7 +318,7 @@ namespace InABox.Clients
 
         public Dictionary<string, CoreTable> Tables { get; set; }
 
-        public override void DeserializeBinary(BinaryReader reader)
+        public override void DeserializeBinary(CoreBinaryReader reader)
         {
             base.DeserializeBinary(reader);
 
@@ -334,7 +334,7 @@ namespace InABox.Clients
             }
         }
 
-        public override void SerializeBinary(BinaryWriter writer)
+        public override void SerializeBinary(CoreBinaryWriter writer)
         {
             base.SerializeBinary(writer);
 

+ 4 - 4
InABox.Core/DataTable.cs

@@ -753,7 +753,7 @@ namespace InABox.Core
 
         #region Serialize Binary
 
-        public void WriteBinary(BinaryWriter writer, bool includeColumns)
+        public void WriteBinary(CoreBinaryWriter writer, bool includeColumns)
         {
             writer.Write(TableName);
 
@@ -779,9 +779,9 @@ namespace InABox.Core
             }
         }
 
-        public void SerializeBinary(BinaryWriter writer) => WriteBinary(writer, true);
+        public void SerializeBinary(CoreBinaryWriter writer) => WriteBinary(writer, true);
 
-        public void ReadBinary(BinaryReader reader, IList<CoreColumn>? columns)
+        public void ReadBinary(CoreBinaryReader reader, IList<CoreColumn>? columns)
         {
             tableName = reader.ReadString();
 
@@ -817,7 +817,7 @@ namespace InABox.Core
             }
         }
 
-        public void DeserializeBinary(BinaryReader reader) => ReadBinary(reader, null);
+        public void DeserializeBinary(CoreBinaryReader reader) => ReadBinary(reader, null);
 
         #endregion
     }

+ 109 - 36
InABox.Core/Serialization.cs

@@ -16,9 +16,9 @@ namespace InABox.Core
 {
     public interface ISerializeBinary
     {
-        public void SerializeBinary(BinaryWriter writer);
+        public void SerializeBinary(CoreBinaryWriter writer);
 
-        public void DeserializeBinary(BinaryReader reader);
+        public void DeserializeBinary(CoreBinaryReader reader);
     }
 
     public static class Serialization
@@ -193,33 +193,101 @@ namespace InABox.Core
 
         #region Binary Serialization
 
-        public static byte[] WriteBinary(this ISerializeBinary obj)
+        public static byte[] WriteBinary(this ISerializeBinary obj, BinarySerializationSettings settings)
         {
             using var stream = new MemoryStream();
-            obj.SerializeBinary(new BinaryWriter(stream));
+            obj.SerializeBinary(new CoreBinaryWriter(stream, settings));
             return stream.ToArray();
         }
 
-        public static T ReadBinary<T>(byte[] data)
-            where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), data);
-        public static T ReadBinary<T>(Stream stream)
-            where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), stream);
+        public static T ReadBinary<T>(byte[] data, BinarySerializationSettings settings)
+            where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), data, settings);
+        public static T ReadBinary<T>(Stream stream, BinarySerializationSettings settings)
+            where T : ISerializeBinary, new() => (T)ReadBinary(typeof(T), stream, settings);
 
-        public static object ReadBinary(Type T, byte[] data)
+        public static object ReadBinary(Type T, byte[] data, BinarySerializationSettings settings)
         {
             using var stream = new MemoryStream(data);
-            return ReadBinary(T, stream);
+            return ReadBinary(T, stream, settings);
         }
-        public static object ReadBinary(Type T, Stream stream)
+        public static object ReadBinary(Type T, Stream stream, BinarySerializationSettings settings)
         {
             var obj = (Activator.CreateInstance(T) as ISerializeBinary)!;
-            obj.DeserializeBinary(new BinaryReader(stream));
+            obj.DeserializeBinary(new CoreBinaryReader(stream, settings));
             return obj;
         }
 
         #endregion
     }
 
+    public class CoreBinaryReader : BinaryReader
+    {
+        public BinarySerializationSettings Settings { get; set; }
+
+        public CoreBinaryReader(Stream stream, BinarySerializationSettings settings): base(stream)
+        {
+            Settings = settings;
+        }
+    }
+    public class CoreBinaryWriter : BinaryWriter
+    {
+        public BinarySerializationSettings Settings { get; set; }
+
+        public CoreBinaryWriter(Stream stream, BinarySerializationSettings settings): base(stream)
+        {
+            Settings = settings;
+        }
+    }
+
+    /// <summary>
+    /// A class to maintain the consistency of serialisation formats across versions.
+    /// The design of this is such that specific versions of serialisation have different parameters set,
+    /// and the versions are maintained as static properties. Please keep the constructor private.
+    /// </summary>
+    /// <remarks>
+    /// Note that <see cref="Latest"/> should always be updated to point to the latest version.
+    /// <br/>
+    /// Note also that all versions should have an entry in the <see cref="ConvertVersionString(string)"/> function.
+    /// <br/>
+    /// Also, if you create a new format, it would probably be a good idea to add a database update script to get all
+    /// <see cref="IPackable"/> and <see cref="ISerializeBinary"/> properties and update the version of the format.
+    /// (Otherwise, we'd basically be nullifying all data that is currently binary serialised.)
+    /// </remarks>
+    public class BinarySerializationSettings
+    {
+        /// <summary>
+        /// Should reference types include a flag for nullability? (Adds an extra boolean field for whether the value is null or not).
+        /// </summary>
+        /// <remarks>
+        /// True in all serialisation versions >= 1.1.
+        /// </remarks>
+        public bool IncludeNullables { get; set; }
+        public string Version { get; set; }
+
+        public static BinarySerializationSettings Latest => V1_1;
+
+        public static BinarySerializationSettings V1_0 = new BinarySerializationSettings("1.0")
+        {
+            IncludeNullables = false
+        };
+        public static BinarySerializationSettings V1_1 = new BinarySerializationSettings("1.1")
+        {
+            IncludeNullables = true
+        };
+
+        public static BinarySerializationSettings ConvertVersionString(string version) => version switch
+        {
+            "1.0" => V1_0,
+            "1.1" => V1_1,
+            _ => V1_0
+        };
+
+        private BinarySerializationSettings(string version)
+        {
+            Version = version;
+        }
+    }
+
     public static class SerializationUtils
     {
         public static void Write(this BinaryWriter writer, Guid guid)
@@ -232,8 +300,8 @@ namespace InABox.Core
         }
 
         /// <summary>
-        /// Binary serialize a bunch of different types of values. <see cref="WriteBinaryValue(BinaryWriter, Type, object?)"/> and
-        /// <see cref="ReadBinaryValue(BinaryReader, Type)"/> are inverses of each other.
+        /// Binary serialize a bunch of different types of values. <see cref="WriteBinaryValue(CoreBinaryWriter, Type, object?)"/> and
+        /// <see cref="ReadBinaryValue(CoreBinaryReader, Type)"/> are inverses of each other.
         /// </summary>
         /// <remarks>
         /// Handles <see cref="byte"/>[], <see cref="Array"/>s of serialisable values, <see cref="Enum"/>, <see cref="bool"/>, <see cref="string"/>,
@@ -245,7 +313,7 @@ namespace InABox.Core
         /// <param name="type"></param>
         /// <param name="value"></param>
         /// <exception cref="Exception">If an object of <paramref name="type"/> is unable to be serialized.</exception>
-        public static void WriteBinaryValue(this BinaryWriter writer, Type type, object? value)
+        public static void WriteBinaryValue(this CoreBinaryWriter writer, Type type, object? value)
         {
             value ??= CoreUtils.GetDefault(type);
             if (type == typeof(byte[]) && value is byte[] bArray)
@@ -329,19 +397,25 @@ namespace InABox.Core
             }
             else if (typeof(IPackable).IsAssignableFrom(type) && value is IPackable pack)
             {
-                writer.Write(true);
+                if (writer.Settings.IncludeNullables)
+                {
+                    writer.Write(true);
+                }
                 pack.Pack(writer);
             }
-            else if (typeof(IPackable).IsAssignableFrom(type) && value is null)
+            else if (writer.Settings.IncludeNullables && typeof(IPackable).IsAssignableFrom(type) && value is null)
             {
                 writer.Write(false);
             }
             else if (typeof(ISerializeBinary).IsAssignableFrom(type) && value is ISerializeBinary binary)
             {
-                writer.Write(true);
+                if (writer.Settings.IncludeNullables)
+                {
+                    writer.Write(true);
+                }
                 binary.SerializeBinary(writer);
             }
-            else if (typeof(ISerializeBinary).IsAssignableFrom(type) && value is null)
+            else if (writer.Settings.IncludeNullables && typeof(ISerializeBinary).IsAssignableFrom(type) && value is null)
             {
                 writer.Write(false);
             }
@@ -364,8 +438,8 @@ namespace InABox.Core
         }
 
         /// <summary>
-        /// Binary deserialize a bunch of different types of values. <see cref="WriteBinaryValue(BinaryWriter, Type, object?)"/> and
-        /// <see cref="ReadBinaryValue(BinaryReader, Type)"/> are inverses of each other.
+        /// Binary deserialize a bunch of different types of values. <see cref="WriteBinaryValue(CoreBinaryWriter, Type, object?)"/> and
+        /// <see cref="ReadBinaryValue(CoreBinaryReader, Type)"/> are inverses of each other.
         /// </summary>
         /// <remarks>
         /// Handles <see cref="byte"/>[], <see cref="Array"/>s of serialisable values, <see cref="Enum"/>, <see cref="bool"/>, <see cref="string"/>,
@@ -373,11 +447,10 @@ namespace InABox.Core
         /// <see cref="DateTime"/>, <see cref="TimeSpan"/>, <see cref="LoggablePropertyAttribute"/>, <see cref="IPackable"/>, <see cref="Nullable{T}"/>
         /// and <see cref="ISerializeBinary"/>.
         /// </remarks>
-        /// <param name="writer"></param>
+        /// <param name="reader"></param>
         /// <param name="type"></param>
-        /// <param name="value"></param>
         /// <exception cref="Exception">If an object of <paramref name="type"/> is unable to be deserialized.</exception>
-        public static object? ReadBinaryValue(this BinaryReader reader, Type type)
+        public static object? ReadBinaryValue(this CoreBinaryReader reader, Type type)
         {
             if (type == typeof(byte[]))
             {
@@ -454,7 +527,7 @@ namespace InABox.Core
             }
             else if (typeof(IPackable).IsAssignableFrom(type))
             {
-                if (reader.ReadBoolean())
+                if (!reader.Settings.IncludeNullables || reader.ReadBoolean()) // Note the short-circuit operator preventing reading a boolean.
                 {
                     var packable = (Activator.CreateInstance(type) as IPackable)!;
                     packable.Unpack(reader);
@@ -467,7 +540,7 @@ namespace InABox.Core
             }
             else if (typeof(ISerializeBinary).IsAssignableFrom(type))
             {
-                if (reader.ReadBoolean())
+                if (!reader.Settings.IncludeNullables || reader.ReadBoolean()) // Note the short-circuit operator preventing reading a boolean.
                 {
                     var obj = (Activator.CreateInstance(type) as ISerializeBinary)!;
                     obj.DeserializeBinary(reader);
@@ -500,7 +573,7 @@ namespace InABox.Core
             DatabaseSchema.Properties(type)
                 .Where(x => !(x is StandardProperty st) || st.Property.GetCustomAttribute<DoNotSerialize>() == null);
 
-        private static void WriteOriginalValues<TObject>(this BinaryWriter writer, TObject obj)
+        private static void WriteOriginalValues<TObject>(this CoreBinaryWriter writer, TObject obj)
             where TObject : BaseObject
         {
             var originalValues = new List<Tuple<Type, string, object?>>();
@@ -519,7 +592,7 @@ namespace InABox.Core
                 writer.WriteBinaryValue(type, value);
             }
         }
-        private static void ReadOriginalValues<TObject>(this BinaryReader reader, TObject obj)
+        private static void ReadOriginalValues<TObject>(this CoreBinaryReader reader, TObject obj)
             where TObject : BaseObject
         {
             var nOriginalValues = reader.ReadInt32();
@@ -534,7 +607,7 @@ namespace InABox.Core
         }
 
         /// <summary>
-        /// An implementation of binary serialising a <typeparamref name="TObject"/>; this is the inverse of <see cref="ReadObject{TObject}(BinaryReader)"/>.
+        /// An implementation of binary serialising a <typeparamref name="TObject"/>; this is the inverse of <see cref="ReadObject{TObject}(CoreBinaryReader)"/>.
         /// </summary>
         /// <remarks>
         /// Also serialises the names of properties along with the values.
@@ -542,7 +615,7 @@ namespace InABox.Core
         /// <typeparam name="TObject"></typeparam>
         /// <param name="writer"></param>
         /// <param name="entity"></param>
-        public static void WriteObject<TObject>(this BinaryWriter writer, TObject entity)
+        public static void WriteObject<TObject>(this CoreBinaryWriter writer, TObject entity)
             where TObject : BaseObject, new()
         {
             var properties = SerializableProperties(typeof(TObject)).ToList();
@@ -557,12 +630,12 @@ namespace InABox.Core
         }
 
         /// <summary>
-        /// The inverse of <see cref="WriteObject{TObject}(BinaryWriter, TObject)"/>.
+        /// The inverse of <see cref="WriteObject{TObject}(CoreBinaryWriter, TObject)"/>.
         /// </summary>
         /// <typeparam name="TObject"></typeparam>
         /// <param name="reader"></param>
         /// <returns></returns>
-        public static TObject ReadObject<TObject>(this BinaryReader reader)
+        public static TObject ReadObject<TObject>(this CoreBinaryReader reader)
             where TObject : BaseObject, new()
         {
             var obj = new TObject();
@@ -581,7 +654,7 @@ namespace InABox.Core
 
         /// <summary>
         /// An implementation of binary serialising multiple <typeparamref name="TObject"/>s;
-        /// this is the inverse of <see cref="ReadObjects{TObject}(BinaryReader)"/>.
+        /// this is the inverse of <see cref="ReadObjects{TObject}(CoreBinaryReader)"/>.
         /// </summary>
         /// <remarks>
         /// Also serialises the names of properties along with the values.
@@ -589,7 +662,7 @@ namespace InABox.Core
         /// <typeparam name="TObject"></typeparam>
         /// <param name="writer"></param>
         /// <param name="entity"></param>
-        public static void WriteObjects<TObject>(this BinaryWriter writer, ICollection<TObject> objects)
+        public static void WriteObjects<TObject>(this CoreBinaryWriter writer, ICollection<TObject> objects)
             where TObject : BaseObject, new()
         {
             var properties = SerializableProperties(typeof(TObject)).ToList();
@@ -612,12 +685,12 @@ namespace InABox.Core
         }
 
         /// <summary>
-        /// The inverse of <see cref="WriteObjects{TObject}(BinaryWriter, IList{TObject})"/>.
+        /// The inverse of <see cref="WriteObjects{TObject}(CoreBinaryWriter, IList{TObject})"/>.
         /// </summary>
         /// <typeparam name="TObject"></typeparam>
         /// <param name="reader"></param>
         /// <returns></returns>
-        public static List<TObject> ReadObjects<TObject>(this BinaryReader reader)
+        public static List<TObject> ReadObjects<TObject>(this CoreBinaryReader reader)
             where TObject : BaseObject, new()
         {
             var objs = new List<TObject>();

+ 29 - 16
InABox.Server/Rest/RestListener.cs

@@ -59,7 +59,13 @@ namespace InABox.API
         
         private RequestData GetRequestData(IRequest request)
         {
-            var data = new RequestData();
+            BinarySerializationSettings settings = BinarySerializationSettings.V1_0;
+            if (request.Query.TryGetValue("serializationVersion", out var versionString))
+            {
+                settings = BinarySerializationSettings.ConvertVersionString(versionString);
+            }
+
+            var data = new RequestData(settings);
             if (request.Query.TryGetValue("format", out var formatString) && Enum.TryParse<SerializationFormat>(formatString, out var format))
             {
                 data.RequestFormat = format;
@@ -174,7 +180,7 @@ namespace InABox.API
         /// <returns></returns>
         private IResponseBuilder GetNotify(IRequest request, RequestData data)
         {
-            var requestObj = Deserialize<NotifyRequest>(request.Content, data.RequestFormat, true);
+            var requestObj = Deserialize<NotifyRequest>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             if (!CredentialsCache.SessionExists(requestObj.Credentials.Session))
             {
                 return request.Respond().Status(ResponseStatus.NotFound);
@@ -194,7 +200,7 @@ namespace InABox.API
 
         private IResponseBuilder Validate(IRequest request, RequestData data)
         {
-            var requestObj = Deserialize<ValidateRequest>(request.Content, data.RequestFormat, true);
+            var requestObj = Deserialize<ValidateRequest>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             var response = RestService.Validate(requestObj);
 
             var serialized = Serialization.Serialize(response);
@@ -205,7 +211,7 @@ namespace InABox.API
 
         private IResponseBuilder Check2FA(IRequest request, RequestData data)
         {
-            var requestObj = Deserialize<Check2FARequest>(request.Content, data.RequestFormat, true);
+            var requestObj = Deserialize<Check2FARequest>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             var response = RestService.Check2FA(requestObj);
 
             var serialized = Serialization.Serialize(response);
@@ -234,47 +240,54 @@ namespace InABox.API
         private class RequestData
         {
             public SerializationFormat RequestFormat { get; set; }
+
+            public BinarySerializationSettings BinarySerializationSettings { get; set; }
+
+            public RequestData(BinarySerializationSettings binarySerializationSettings)
+            {
+                BinarySerializationSettings = binarySerializationSettings;
+            }
         }
 
         private static QueryResponse<T> List<T>(IRequest request, RequestData data) where T : Entity, new()
         {
-            var requestObject = Deserialize<QueryRequest<T>>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<QueryRequest<T>>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             return RestService<T>.List(requestObject);
         }
         private static SaveResponse<T> Save<T>(IRequest request, RequestData data) where T : Entity, new()
         {
-            var requestObject = Deserialize<SaveRequest<T>>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<SaveRequest<T>>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             return RestService<T>.Save(requestObject);
         }
         private static DeleteResponse<T> Delete<T>(IRequest request, RequestData data) where T : Entity, new()
         {
-            var requestObject = Deserialize<DeleteRequest<T>>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<DeleteRequest<T>>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             return RestService<T>.Delete(requestObject);
         }
         private static MultiSaveResponse<T> MultiSave<T>(IRequest request, RequestData data) where T : Entity, new()
         {
-            var requestObject = Deserialize<MultiSaveRequest<T>>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<MultiSaveRequest<T>>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             return RestService<T>.MultiSave(requestObject);
         }
         private static MultiDeleteResponse<T> MultiDelete<T>(IRequest request, RequestData data) where T : Entity, new()
         {
-            var requestObject = Deserialize<MultiDeleteRequest<T>>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<MultiDeleteRequest<T>>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
             return RestService<T>.MultiDelete(requestObject);
         }
         private static MultiQueryResponse QueryMultiple(IRequest request, RequestData data)
         {
-            var requestObject = Deserialize<MultiQueryRequest>(request.Content, data.RequestFormat, true);
+            var requestObject = Deserialize<MultiQueryRequest>(request.Content, data.RequestFormat, data.BinarySerializationSettings, true);
 
             return RestService.QueryMultiple(requestObject, false);
         }
 
-        private static T Deserialize<T>(Stream? stream, SerializationFormat requestFormat, bool strict = false)
+        private static T Deserialize<T>(Stream? stream, SerializationFormat requestFormat, BinarySerializationSettings binarySettings, bool strict = false)
         {
             if (stream is null)
                 throw new Exception("Stream is null");
             if (requestFormat == SerializationFormat.Binary && typeof(T).IsAssignableTo(typeof(ISerializeBinary)))
             {
-                return (T)Serialization.ReadBinary(typeof(T), stream);
+                return (T)Serialization.ReadBinary(typeof(T), stream, binarySettings);
             }
             else
             {
@@ -284,12 +297,12 @@ namespace InABox.API
             }
         }
 
-        private IResponseBuilder SerializeResponse(IRequest request, SerializationFormat responseFormat, Response? result)
+        private IResponseBuilder SerializeResponse(IRequest request, SerializationFormat responseFormat, BinarySerializationSettings binarySettings, Response? result)
         {
             if (responseFormat == SerializationFormat.Binary && result is ISerializeBinary binary)
             {
                 var stream = new MemoryStream();
-                binary.SerializeBinary(new BinaryWriter(stream));
+                binary.SerializeBinary(new CoreBinaryWriter(stream, binarySettings));
 
                 var response = request.Respond()
                     .Type(new FlexibleContentType(ContentType.ApplicationOctetStream))
@@ -326,7 +339,7 @@ namespace InABox.API
             if (endpoint.StartsWith("QueryMultiple"))
             {
                 var result = QueryMultiple(request, requestData);
-                return new ValueTask<IResponse?>(SerializeResponse(request, responseFormat, result).Build());
+                return new ValueTask<IResponse?>(SerializeResponse(request, responseFormat, requestData.BinarySerializationSettings, result).Build());
             }
 
             foreach (var (name, method) in methodMap)
@@ -346,7 +359,7 @@ namespace InABox.API
                         var resolvedMethod = method.MakeGenericMethod(entityType);
                         var result = resolvedMethod.Invoke(null, new object[] { request, requestData }) as Response;
 
-                        return new ValueTask<IResponse?>(SerializeResponse(request, responseFormat, result).Build());
+                        return new ValueTask<IResponse?>(SerializeResponse(request, responseFormat, requestData.BinarySerializationSettings, result).Build());
                     }
 
                     Logger.Send(LogType.Error, request.Client.IPAddress.ToString(),

+ 1 - 1
inabox.wpf/DynamicGrid/DynamicGrid.cs

@@ -2655,7 +2655,7 @@ namespace InABox.DynamicGrid
                     var values = editor.Values(colname, items);
                     Dispatcher.Invoke(
                         () =>
-                        {
+                        { 
                             try
                             {
                                 //Logger.Send(LogType.Information, typeof(T).Name, "Dispatching Results" + colname);