diff --git a/FxEvents/FiveMMsgPack/MsgPack.dll b/FxEvents/FiveMMsgPack/MsgPack.dll
new file mode 100644
index 0000000..2cbc628
Binary files /dev/null and b/FxEvents/FiveMMsgPack/MsgPack.dll differ
diff --git a/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs b/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs
index 44f68b6..7854f7d 100644
--- a/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs
+++ b/FxEvents/FxEvents.Client/EventSystem/ClientGateway.cs
@@ -21,7 +21,7 @@ public class ClientGateway : BaseGateway
public ClientGateway()
{
SnowflakeGenerator.Create((short)new Random().Next(1, 199));
- Serialization = new BinarySerialization();
+ Serialization = new MsgPackSerialization();
DelayDelegate = async delay => await BaseScript.Delay(delay);
PrepareDelegate = PrepareAsync;
PushDelegate = Push;
diff --git a/FxEvents/FxEvents.Client/FxEvents.Client.csproj b/FxEvents/FxEvents.Client/FxEvents.Client.csproj
index 7db017a..0dcbb86 100644
--- a/FxEvents/FxEvents.Client/FxEvents.Client.csproj
+++ b/FxEvents/FxEvents.Client/FxEvents.Client.csproj
@@ -31,6 +31,9 @@
4
+
+ ..\FiveMMsgPack\MsgPack.dll
+
@@ -40,16 +43,11 @@
$(PkgNewtonsoft_Json)\lib\portable-net40+sl5+win8+wp8+wpa81\Newtonsoft.Json.dll
-
-
-
-
-
-
+
diff --git a/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs b/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs
index 9e3f561..ff8da68 100644
--- a/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs
+++ b/FxEvents/FxEvents.Server/EventSystem/ServerGateway.cs
@@ -23,7 +23,7 @@ public class ServerGateway : BaseGateway
public ServerGateway()
{
SnowflakeGenerator.Create((short)new Random().Next(200, 399));
- Serialization = new BinarySerialization();
+ Serialization = new MsgPackSerialization();
DelayDelegate = async delay => await BaseScript.Delay(delay);
PushDelegate = Push;
_signatures = new();
diff --git a/FxEvents/FxEvents.Server/FxEvents.Server.csproj b/FxEvents/FxEvents.Server/FxEvents.Server.csproj
index 4881f7c..a47e4ee 100644
--- a/FxEvents/FxEvents.Server/FxEvents.Server.csproj
+++ b/FxEvents/FxEvents.Server/FxEvents.Server.csproj
@@ -9,12 +9,12 @@
x64
SERVER
- embedded
+ portable
SERVER
- embedded
+ portable
@@ -22,9 +22,12 @@
-
+
+
+ ..\FiveMMsgPack\MsgPack.dll
+
$(PkgNewtonsoft_Json)\lib\portable-net40+sl5+win8+wp8+wpa81\Newtonsoft.Json.dll
diff --git a/FxEvents/Shared/BinaryHelper.cs b/FxEvents/Shared/BinaryHelper.cs
index 085e8d8..1848af1 100644
--- a/FxEvents/Shared/BinaryHelper.cs
+++ b/FxEvents/Shared/BinaryHelper.cs
@@ -9,11 +9,12 @@ namespace FxEvents.Shared
{
public static class BinaryHelper
{
- private static BinarySerialization _serialization = new();
+ private static BinarySerialization binarySerialization = new();
+ private static MsgPackSerialization msgpackSerialization = new();
public static byte[] ToBytes(this T obj)
{
- using SerializationContext context = new("BinaryHelper", "ToBytes", _serialization);
+ using SerializationContext context = new("BinaryHelper", "ToBytes", msgpackSerialization);
context.Serialize(typeof(T), obj);
return context.GetData();
}
@@ -39,7 +40,7 @@ public static string BytesToString(this byte[] ba, bool separator = false, bool
public static T FromBytes(this byte[] data)
{
- using SerializationContext context = new(data.ToString(), "FromBytes", _serialization, data);
+ using SerializationContext context = new(data.ToString(), "FromBytes", msgpackSerialization, data);
return context.Deserialize();
}
}
diff --git a/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs b/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs
index 747a2bd..7582e7c 100644
--- a/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs
+++ b/FxEvents/Shared/EventSubsystem/Message/EventParameter.cs
@@ -7,6 +7,7 @@ public class EventParameter
{
public byte[] Data { get; set; }
+ public EventParameter() { }
public EventParameter(byte[] data)
{
Data = data;
diff --git a/FxEvents/Shared/EventSubsystem/Message/EventResponseMessage.cs b/FxEvents/Shared/EventSubsystem/Message/EventResponseMessage.cs
index 9709ab5..30c98f9 100644
--- a/FxEvents/Shared/EventSubsystem/Message/EventResponseMessage.cs
+++ b/FxEvents/Shared/EventSubsystem/Message/EventResponseMessage.cs
@@ -12,6 +12,7 @@ public class EventResponseMessage : IMessage
public string? Signature { get; set; }
public byte[]? Data { get; set; }
+ public EventResponseMessage() { }
public EventResponseMessage(Snowflake id, string endpoint, string? signature, byte[]? data)
{
Id = id;
diff --git a/FxEvents/Shared/EventSubsystem/Serialization/Implementations/BinarySerialization.cs b/FxEvents/Shared/EventSubsystem/Serialization/Implementations/BinarySerialization.cs
index 1ee6bd0..3a329ee 100644
--- a/FxEvents/Shared/EventSubsystem/Serialization/Implementations/BinarySerialization.cs
+++ b/FxEvents/Shared/EventSubsystem/Serialization/Implementations/BinarySerialization.cs
@@ -15,6 +15,7 @@ namespace FxEvents.Shared.Serialization.Implementations
public delegate T DeserializationObjectActivator(BinaryReader reader);
+ [Obsolete("This implementations is obsolete now that MsgPack is available")]
public class BinarySerialization : ISerialization
{
public const string PackMethod = "PackSerializedBytes";
diff --git a/FxEvents/Shared/EventSubsystem/Serialization/Implementations/MsgPackSerialization.cs b/FxEvents/Shared/EventSubsystem/Serialization/Implementations/MsgPackSerialization.cs
new file mode 100644
index 0000000..0f85a99
--- /dev/null
+++ b/FxEvents/Shared/EventSubsystem/Serialization/Implementations/MsgPackSerialization.cs
@@ -0,0 +1,270 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Text;
+using FxEvents.Shared.Diagnostics;
+using FxEvents.Shared.Exceptions;
+using FxEvents.Shared.TypeExtensions;
+using Logger;
+using MsgPack.Serialization;
+
+namespace FxEvents.Shared.Serialization.Implementations
+{
+ public class MsgPackSerialization : ISerialization
+ {
+ private delegate T ObjectActivator();
+ private delegate void VoidMethod();
+ private Log logger = new();
+ private MsgPack.Serialization.SerializationContext _context = new(MsgPack.PackerCompatibilityOptions.None) { SerializationMethod = SerializationMethod.Map };
+ public MsgPackSerialization()
+ {
+ }
+
+ private bool CanCreateInstanceUsingDefaultConstructor(Type t) => t.IsValueType || !t.IsAbstract && t.GetConstructor(Type.EmptyTypes) != null;
+ public void Serialize(Type type, object value, SerializationContext context)
+ {
+ var typeIdentifier = GetTypeIdentifier(type);
+ if (typeIdentifier == "System.Collections.Generic.KeyValuePair`2")
+ {
+ var generics = type.GetGenericArguments();
+ var method = GetType().GetMethod("Serialize",
+ new[] { typeof(Type), typeof(object), typeof(SerializationContext) });
+ var instanceParam = Expression.Parameter(typeof(MsgPackSerialization), "instance");
+ var typeParam = Expression.Parameter(typeof(Type), "type");
+ var contextParam = Expression.Parameter(typeof(SerializationContext), "context");
+ var pairParam = Expression.Parameter(type, "pair");
+ var valueParam = Expression.Parameter(typeof(object), "value");
+ var call = Expression.Call(instanceParam, method!, typeParam, valueParam, contextParam);
+
+ void CallSerialization(Type genericType, string property)
+ {
+ var action = (Action)Expression.Lambda(typeof(Action), Expression.Block(new[]
+ {
+ instanceParam,
+ typeParam,
+ contextParam,
+ pairParam,
+ valueParam
+ },
+ Expression.Assign(instanceParam, Expression.Constant(this, typeof(MsgPackSerialization))),
+ Expression.Assign(contextParam, Expression.Constant(context, typeof(SerializationContext))),
+ Expression.Assign(typeParam, Expression.Constant(genericType, typeof(Type))),
+ Expression.Assign(pairParam, Expression.Constant(value, type)),
+ Expression.Assign(valueParam,
+ Expression.Convert(Expression.Property(pairParam, property), typeof(object))),
+ call
+ )).Compile();
+
+ action.Invoke();
+ }
+
+ CallSerialization(generics[0], "Key");
+ CallSerialization(generics[1], "Value");
+ }
+ else if (typeIdentifier.StartsWith("System.Tuple`"))
+ {
+ var generics = type.GetGenericArguments();
+ var method = GetType().GetMethod("Serialize",
+ new[] { typeof(Type), typeof(object), typeof(SerializationContext) });
+ var instanceParam = Expression.Parameter(typeof(MsgPackSerialization), "instance");
+ var typeParam = Expression.Parameter(typeof(Type), "type");
+ var valueParam = Expression.Parameter(type, "value");
+ var contextParam = Expression.Parameter(typeof(SerializationContext), "context");
+
+ for (var idx = 0; idx < generics.Length; idx++)
+ {
+ var generic = generics[idx];
+ var call = Expression.Call(instanceParam, method!, typeParam,
+ Expression.Convert(Expression.Property(valueParam, $"Item{idx + 1}"), typeof(object)),
+ contextParam);
+ var action = (Action)Expression.Lambda(typeof(Action), Expression.Block(new[]
+ {
+ instanceParam,
+ typeParam,
+ contextParam,
+ valueParam
+ },
+ Expression.Assign(instanceParam, Expression.Constant(this, typeof(MsgPackSerialization))),
+ Expression.Assign(contextParam, Expression.Constant(context, typeof(SerializationContext))),
+ Expression.Assign(typeParam, Expression.Constant(generic, typeof(Type))),
+ Expression.Assign(valueParam, Expression.Constant(value, type)),
+ call
+ )).Compile();
+
+ action.Invoke();
+ }
+ }
+ else
+ {
+ var ser = MessagePackSerializer.Get(type, _context);
+ ser.Pack(context.Writer.BaseStream, value);
+ }
+ }
+
+ public void Serialize(T value, SerializationContext context)
+ {
+ Serialize(typeof(T), value, context);
+ }
+
+ public object Deserialize(Type type, SerializationContext context)
+ {
+ var ser = MessagePackSerializer.Get(type, _context);
+ return ser.Unpack(context.Reader.BaseStream);
+ }
+
+ public T Deserialize(SerializationContext context) => Deserialize(typeof(T), context);
+
+ public T Deserialize(Type type, SerializationContext context)
+ {
+ var canInstance = CanCreateInstanceUsingDefaultConstructor(type);
+ var typeIdentifier = GetTypeIdentifier(type);
+
+ if (TypeCache.IsSimpleType)
+ {
+ var primitive = Deserialize(type, context);
+ if (primitive != null) return (T)primitive;
+ }
+ if (typeIdentifier == "System.Collections.Generic.KeyValuePair`2")
+ {
+ var generics = type.GetGenericArguments();
+ var constructor = type.GetConstructor(generics) ??
+ throw new SerializationException(context, type,
+ $"Could not find suitable constructor for type: {type.Name}");
+
+ var key = DeserializeAnonymously(generics[0], context);
+ var value = DeserializeAnonymously(generics[1], context);
+ var keyParam = Expression.Parameter(generics[0], "key");
+ var valueParam = Expression.Parameter(generics[1], "value");
+ var block = Expression.Block(
+ new[] { keyParam, valueParam },
+ Expression.Assign(keyParam, Expression.Constant(key, generics[0])),
+ Expression.Assign(valueParam, Expression.Constant(value, generics[1])),
+ Expression.New(constructor, keyParam, valueParam)
+ );
+
+ if (typeof(T) == typeof(object))
+ {
+ var generic = typeof(ObjectActivator<>).MakeGenericType(type);
+ var activator = Expression.Lambda(generic, block).Compile();
+
+ return (T)activator.DynamicInvoke();
+ }
+ else
+ {
+ var activator =
+ (ObjectActivator)Expression.Lambda(typeof(ObjectActivator), block).Compile();
+
+ return activator.Invoke();
+ }
+ }
+ else if (typeIdentifier.StartsWith("System.Tuple`"))
+ {
+ var generics = type.GetGenericArguments();
+ var constructor = type.GetConstructor(generics) ??
+ throw new SerializationException(context, type,
+ $"Could not find suitable constructor for type: {type.Name}");
+ var parameters = new List();
+
+ foreach (var generic in generics)
+ {
+ var entry = Deserialize(generic, context);
+
+ parameters.Add(Expression.Constant(entry, generic));
+ }
+
+ var expression = Expression.New(constructor, parameters);
+
+ if (typeof(T) == typeof(object))
+ {
+ var generic = typeof(ObjectActivator<>).MakeGenericType(type);
+ var activator = Expression.Lambda(generic, expression).Compile();
+
+ return (T)activator.DynamicInvoke();
+ }
+ else
+ {
+ var activator =
+ (ObjectActivator)Expression.Lambda(typeof(ObjectActivator), expression).Compile();
+
+ return activator.Invoke();
+ }
+ }
+ else
+ {
+ if (!canInstance)
+ {
+ throw new SerializationException(context, type, $"Type {type.Name} is missing its emtpy constructor");
+ }
+ var ser = MessagePackSerializer.Get(_context);
+ return ser.Unpack(context.Reader.BaseStream);
+ }
+ }
+
+ public object DeserializeAnonymously(Type type, SerializationContext context) =>
+ Deserialize