1
This commit is contained in:
231
Assets/BITKit/Core/Binary/BITBinary.cs
Normal file
231
Assets/BITKit/Core/Binary/BITBinary.cs
Normal file
@@ -0,0 +1,231 @@
|
||||
#if NET5_0_OR_GREATER
|
||||
#else
|
||||
using UnityEngine;
|
||||
#endif
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using Microsoft.SqlServer.Server;
|
||||
#if NET5_0_OR_GREATER
|
||||
using Microsoft.SqlServer.Server;
|
||||
#endif
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BITKit
|
||||
{
|
||||
public class BITBinary
|
||||
{
|
||||
private static readonly Dictionary<string, INetMessageReader> netReaders = new();
|
||||
public static readonly List<Type> serializableTypes = new();
|
||||
|
||||
public static async UniTask Start()
|
||||
{
|
||||
netReaders.Clear();
|
||||
#if NET5_0_OR_GREATER
|
||||
serializableTypes.Clear();
|
||||
#endif
|
||||
var stringBuilder = new StringBuilder();
|
||||
foreach (var x in await ReflectionHelper.GetInstances<INetMessageReader>())
|
||||
{
|
||||
var typeName = x.GetMessageType().FullName;
|
||||
if (typeName == null) continue;
|
||||
netReaders.Add(typeName, x);
|
||||
stringBuilder.AppendLine(typeName);
|
||||
}
|
||||
|
||||
var serializes = await ReflectionHelper.GetInstances<IBinarySerialize>();
|
||||
#if NET5_0_OR_GREATER
|
||||
#else
|
||||
serializes = serializes.Where(x => x.GetType().IsAssignableFrom(typeof(UnityEngine.Object)) is false);
|
||||
#endif
|
||||
foreach (var x in serializes)
|
||||
{
|
||||
serializableTypes.Add(x.GetType());
|
||||
//BIT4Log.Log<BITBinary>($"已注册类型:{x.GetType().FullName}");
|
||||
stringBuilder.AppendLine(x.GetType().FullName);
|
||||
}
|
||||
|
||||
BIT4Log.Log<BITBinary>($"已注册类型:\n{stringBuilder}");
|
||||
}
|
||||
|
||||
public static T Read<T>(byte[] buffer) => (T)ReadAsValue(buffer);
|
||||
public static object ReadAsValue(byte[] buffer)
|
||||
{
|
||||
using var ms = new MemoryStream(buffer);
|
||||
using var reader = new BinaryReader(ms);
|
||||
return Read(reader);
|
||||
}
|
||||
|
||||
public static object Read(BinaryReader reader)
|
||||
{
|
||||
// 检测是否为数组
|
||||
if (reader.ReadBoolean())
|
||||
{
|
||||
//读取数组类型的名称
|
||||
var arrayTypeName = reader.ReadString();
|
||||
//获取数组类型
|
||||
var arrayType = BITSharp.GetTypeFromFullName(arrayTypeName);
|
||||
if(string.IsNullOrEmpty(arrayTypeName) || arrayType is null)
|
||||
throw new Exception($"未找到类型:{arrayTypeName}");
|
||||
//创建数组实例
|
||||
var array = Array.CreateInstance(arrayType, reader.ReadInt32());
|
||||
//循环Reader
|
||||
for (var i = 0; i < array.Length; i++)
|
||||
{
|
||||
//设置值
|
||||
array.SetValue(ReadInternel(reader),i);
|
||||
}
|
||||
//返回数组
|
||||
return array;
|
||||
}
|
||||
|
||||
return ReadInternel(reader);
|
||||
|
||||
object ReadInternel(BinaryReader reader)
|
||||
{
|
||||
var typeName = reader.ReadString();
|
||||
|
||||
if (netReaders.TryGetValue(typeName, out var netReader))
|
||||
return netReader.ReadBinaryAsObject(reader);
|
||||
|
||||
var type = BITSharp.GetTypeFromFullName(typeName);
|
||||
|
||||
if (type is null)
|
||||
{
|
||||
throw new Exception($"反序列化时未找到类型:{typeName}");
|
||||
}
|
||||
|
||||
var instance = System.Activator.CreateInstance(type);
|
||||
|
||||
if (instance is IBinarySerialize serialize)
|
||||
{
|
||||
serialize.Read(reader);
|
||||
return instance;
|
||||
}
|
||||
|
||||
var json = reader.ReadString();
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
throw new Exception($"从二进制中读取的json值为空");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
if (BITSharp.TryGetTypeFromFullName(typeName, out type))
|
||||
return JsonConvert.DeserializeObject(json, type);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Warning<BITBinary>($"反序列化失败,类型:{typeName},值:\n{json}");
|
||||
BIT4Log.LogException(e);
|
||||
}
|
||||
|
||||
throw new Exception("未找到读取该二进制的BinaryReader");
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] WriteAsBytes(object value)
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new BinaryWriter(ms);
|
||||
Write(writer, value);
|
||||
return ms.ToArray();
|
||||
}
|
||||
public static void Write(BinaryWriter writer, object value)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (value is not string && value is IList enumerable)
|
||||
{
|
||||
var pars = enumerable.Cast<object>().ToArray();
|
||||
writer.Write(true);
|
||||
writer.Write(value.GetType().GetElementType()!.FullName!);
|
||||
writer.Write(pars.Length);
|
||||
foreach (var obj in pars)
|
||||
{
|
||||
WriteInterel(writer, obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write(false);
|
||||
WriteInterel(writer,value);
|
||||
}
|
||||
return;
|
||||
void WriteInterel(BinaryWriter writer, object value)
|
||||
{
|
||||
var typeName = value.GetType().FullName;
|
||||
writer.Write(typeName!);
|
||||
if (netReaders.TryGetValue(typeName, out var netReader))
|
||||
{
|
||||
netReader.WriteBinaryAsObject(writer,value);
|
||||
}
|
||||
else if (value is IBinarySerialize serialize)
|
||||
{
|
||||
serialize.Write(writer);
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
writer.Write(JsonConvert.SerializeObject(value));
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
BIT4Log.Warning<BITBinary>(typeName);
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
|
||||
}
|
||||
public static bool IsSupport(object obj) => IsSupport(obj.GetType().FullName);
|
||||
public static bool IsSupport(Type type) => IsSupport(type.FullName);
|
||||
public static bool IsSupport<T>() => IsSupport(typeof(T).FullName);
|
||||
public static bool IsSupport(string typeName)
|
||||
{
|
||||
return netReaders.ContainsKey(typeName) || serializableTypes.Any(x => x.FullName == typeName);
|
||||
}
|
||||
|
||||
public static bool TryWrite(object obj, out byte[] bytes)
|
||||
{
|
||||
bytes = null;
|
||||
if (IsSupport(obj))
|
||||
{
|
||||
bytes = WriteAsBytes(obj);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new BinaryWriter(ms);
|
||||
try
|
||||
{
|
||||
writer.Write(obj!.GetType()!.FullName!);
|
||||
var json = JsonHelper.Get(obj);
|
||||
writer.Write(json);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
BIT4Log.Log(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
return true;
|
||||
//bytes = null;
|
||||
//return false;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user