using System; using System.Collections.Generic; using System.IO; using System.Runtime.Serialization; using System.Threading.Tasks; namespace ZeroLevel.Services.Serialization { public static class MessageSerializer { public static byte[] Serialize(T obj) where T : IBinarySerializable { if (obj == null) return null; using (var writer = new MemoryStreamWriter()) { obj.Serialize(writer); return writer.Complete(); } } public static byte[] Serialize(IEnumerable items) where T : IBinarySerializable { if (items == null) return null; using (var writer = new MemoryStreamWriter()) { writer.WriteCollection(items); return writer.Complete(); } } public static Action GetSerializer() { var t = typeof(T); if (t.IsAssignableTo(typeof(IBinarySerializable))) { return (w, o) => ((IBinarySerializable)o).Serialize(w); } return (w, o) => PrimitiveTypeSerializer.Serialize(w, o); } public static Func GetDeserializer() { if (typeof(IBinarySerializable).IsAssignableFrom(typeof(T))) { return (r) => { var o = (IBinarySerializable)FormatterServices.GetUninitializedObject(typeof(T)); o.Deserialize(r); return (T)o; }; } return (r) => PrimitiveTypeSerializer.Deserialize(r); } static bool TryObjectDeserialize(MemoryStreamReader reader, out T output) { try { var o = (IBinarySerializable)FormatterServices.GetUninitializedObject(typeof(T)); o.Deserialize(reader); output = (T)o; return true; } catch (Exception ex) { Log.SystemError(ex, $"[MessageSerializer.TryObjectDeserialize] Fault deserialize type {typeof(T).Name}"); output = default; } return false; } static bool TryPrimitiveTypeDeserialize(MemoryStreamReader reader, out T output) { try { output = PrimitiveTypeSerializer.Deserialize(reader); return true; } catch (Exception ex) { Log.SystemError(ex, $"[MessageSerializer.TryPrimitiveTypeDeserialize] Fault deserialize type {typeof(T).Name}"); output = default; } return false; } public static byte[] SerializeCompatible(object obj) { if (null == obj) { return null; } var direct_seriazlizable = (obj as IBinarySerializable); if (direct_seriazlizable != null) { using (var writer = new MemoryStreamWriter()) { direct_seriazlizable.Serialize(writer); return writer.Complete(); } } using (var writer = new MemoryStreamWriter()) { PrimitiveTypeSerializer.Serialize(writer, obj); return writer.Complete(); } } public static void SerializeCompatible(this MemoryStreamWriter writer, object obj) { var direct_seriazlizable = (obj as IBinarySerializable); if (direct_seriazlizable != null) { direct_seriazlizable.Serialize(writer); } else { PrimitiveTypeSerializer.Serialize(writer, obj); } } public static byte[] SerializeCompatible(T obj) { if (null == obj) { return null; } var direct_seriazlizable = (obj as IBinarySerializable); if (direct_seriazlizable != null) { using (var writer = new MemoryStreamWriter()) { direct_seriazlizable.Serialize(writer); return writer.Complete(); } } using (var writer = new MemoryStreamWriter()) { PrimitiveTypeSerializer.Serialize(writer, obj); return writer.Complete(); } } public static T Deserialize(byte[] data) where T : IBinarySerializable { if (data == null || data.Length == 0) return default(T); using (var reader = new MemoryStreamReader(data)) { var result = Activator.CreateInstance(); result.Deserialize(reader); return result; } } public static object Deserialize(Type type, byte[] data) { if (data == null || data.Length == 0) return null; using (var reader = new MemoryStreamReader(data)) { var result = (IBinarySerializable)Activator.CreateInstance(type); result.Deserialize(reader); return result; } } public static List DeserializeCollection(byte[] data) where T : IBinarySerializable { List collection = null; if (data != null && data.Length > 0) { using (var reader = new MemoryStreamReader(data)) { int count = reader.ReadInt32(); collection = new List(count); if (count > 0) { for (int i = 0; i < count; i++) { var item = Activator.CreateInstance(); item.Deserialize(reader); collection.Add(item); } } } } return collection; } public static IEnumerable DeserializeCollectionLazy(byte[] data) where T : IBinarySerializable { if (data != null && data.Length > 0) { using (var reader = new MemoryStreamReader(data)) { int count = reader.ReadInt32(); if (count > 0) { for (int i = 0; i < count; i++) { var item = Activator.CreateInstance(); item.Deserialize(reader); yield return item; } } } } } public static T DeserializeCompatible(byte[] data) { if (data == null || data.Length == 0) return default(T)!; if (typeof(IBinarySerializable).IsAssignableFrom(typeof(T))) { using (var reader = new MemoryStreamReader(data)) { var direct = (IBinarySerializable)Activator.CreateInstance()!; direct.Deserialize(reader); return (T)direct; } } using (var reader = new MemoryStreamReader(data)) { return PrimitiveTypeSerializer.Deserialize(reader); } } public static T DeserializeCompatible(IBinaryReader reader) { if (typeof(IBinarySerializable).IsAssignableFrom(typeof(T))) { var direct = (IBinarySerializable)Activator.CreateInstance()!; direct.Deserialize(reader); return (T)direct; } return PrimitiveTypeSerializer.Deserialize(reader); } public static async Task DeserializeCompatibleAsync(IAsyncBinaryReader reader) { if (typeof(IAsyncBinarySerializable).IsAssignableFrom(typeof(T))) { var direct = (IAsyncBinarySerializable)Activator.CreateInstance()!; await direct.DeserializeAsync(reader); return (T)direct; } return PrimitiveTypeSerializer.Deserialize((reader as IBinaryReader)!); } public static object DeserializeCompatible(Type type, byte[] data) { if (data == null || data.Length == 0) return null!; if (typeof(IBinarySerializable).IsAssignableFrom(type)) { using (var reader = new MemoryStreamReader(data)) { var direct = (IBinarySerializable)Activator.CreateInstance(type); direct.Deserialize(reader); return direct; } } using (var reader = new MemoryStreamReader(data)) { return PrimitiveTypeSerializer.Deserialize(reader, type); } } public static T Copy(T value) where T : IBinarySerializable { if (null == value) return default!; using (var writer = new MemoryStreamWriter()) { value.Serialize(writer); using (var reader = new MemoryStreamReader(writer.Complete())) { var direct = (IBinarySerializable)Activator.CreateInstance(); direct.Deserialize(reader); return (T)direct; } } } public static T CopyCompatible(T value) { if (typeof(IBinarySerializable).IsAssignableFrom(typeof(T))) { using (var writer = new MemoryStreamWriter()) { (value as IBinarySerializable)?.Serialize(writer); using (var reader = new MemoryStreamReader(writer.Complete())) { var direct = (IBinarySerializable)Activator.CreateInstance()!; direct.Deserialize(reader); return (T)direct; } } } using (var writer = new MemoryStreamWriter()) { PrimitiveTypeSerializer.Serialize(writer, value); using (var reader = new MemoryStreamReader(writer.Complete())) { return PrimitiveTypeSerializer.Deserialize(reader); } } } #region Stream public static void Serialize(Stream stream, T obj) where T : IBinarySerializable { if (obj == null) return; using (var writer = new MemoryStreamWriter(stream)) { obj.Serialize(writer); } } public static void Serialize(Stream stream, IEnumerable items) where T : IBinarySerializable { if (items == null) return; using (var writer = new MemoryStreamWriter(stream)) { writer.WriteCollection(items); } } public static void SerializeCompatible(Stream stream, object obj) { if (null == obj) { return; } var direct_seriazlizable = (obj as IBinarySerializable); if (direct_seriazlizable != null) { using (var writer = new MemoryStreamWriter(stream)) { direct_seriazlizable.Serialize(writer); } } else { using (var writer = new MemoryStreamWriter(stream)) { PrimitiveTypeSerializer.Serialize(writer, obj); } } } public static void SerializeCompatible(Stream stream, T obj) { if (null == obj) { return; } var direct_seriazlizable = (obj as IBinarySerializable); if (direct_seriazlizable != null) { using (var writer = new MemoryStreamWriter(stream)) { direct_seriazlizable.Serialize(writer); } } else { using (var writer = new MemoryStreamWriter(stream)) { PrimitiveTypeSerializer.Serialize(writer, obj); } } } public static T Deserialize(Stream stream) where T : IBinarySerializable { if (stream == null) return default(T); using (var reader = new MemoryStreamReader(stream)) { var result = Activator.CreateInstance(); result.Deserialize(reader); return result; } } public static object Deserialize(Type type, Stream stream) { if (stream == null) return null; using (var reader = new MemoryStreamReader(stream)) { var result = (IBinarySerializable)Activator.CreateInstance(type); result.Deserialize(reader); return result; } } public static List DeserializeCollection(Stream stream) where T : IBinarySerializable { List collection = null; if (stream != null) { using (var reader = new MemoryStreamReader(stream)) { int count = reader.ReadInt32(); collection = new List(count); if (count > 0) { for (int i = 0; i < count; i++) { var item = Activator.CreateInstance(); item.Deserialize(reader); collection.Add(item); } } } } return collection; } public static IEnumerable DeserializeCollectionLazy(Stream stream) where T : IBinarySerializable { if (stream != null) { using (var reader = new MemoryStreamReader(stream)) { int count = reader.ReadInt32(); if (count > 0) { for (int i = 0; i < count; i++) { var item = Activator.CreateInstance(); item.Deserialize(reader); yield return item; } } } } } public static T DeserializeCompatible(Stream stream) { if (stream == null) return default(T); if (typeof(IBinarySerializable).IsAssignableFrom(typeof(T))) { using (var reader = new MemoryStreamReader(stream)) { var direct = (IBinarySerializable)Activator.CreateInstance(); direct.Deserialize(reader); return (T)direct; } } using (var reader = new MemoryStreamReader(stream)) { return PrimitiveTypeSerializer.Deserialize(reader); } } public static object DeserializeCompatible(Type type, Stream stream) { if (stream == null) return null; if (typeof(IBinarySerializable).IsAssignableFrom(type)) { using (var reader = new MemoryStreamReader(stream)) { var direct = (IBinarySerializable)Activator.CreateInstance(type); direct.Deserialize(reader); return direct; } } using (var reader = new MemoryStreamReader(stream)) { return PrimitiveTypeSerializer.Deserialize(reader, type); } } #endregion } }