Files
TEngine/Assets/GameScripts/DotNet/Core/Serialize/MongoHelper.cs
ALEXTANG 336d4b2eb9 [+] 接入ET8服务端
[+] 接入ET8服务端
2023-07-13 12:23:48 +08:00

250 lines
8.1 KiB
C#

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Reflection;
using MongoDB.Bson;
using MongoDB.Bson.IO;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Bson.Serialization.Serializers;
using TrueSync;
using Unity.Mathematics;
namespace ET
{
public static class MongoHelper
{
private class StructBsonSerialize<TValue>: StructSerializerBase<TValue> where TValue : struct
{
public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
{
Type nominalType = args.NominalType;
IBsonWriter bsonWriter = context.Writer;
bsonWriter.WriteStartDocument();
FieldInfo[] fields = nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
foreach (FieldInfo field in fields)
{
bsonWriter.WriteName(field.Name);
BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value));
}
bsonWriter.WriteEndDocument();
}
public override TValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
//boxing is required for SetValue to work
object obj = new TValue();
Type actualType = args.NominalType;
IBsonReader bsonReader = context.Reader;
bsonReader.ReadStartDocument();
while (bsonReader.State != BsonReaderState.EndOfDocument)
{
switch (bsonReader.State)
{
case BsonReaderState.Name:
{
string name = bsonReader.ReadName(Utf8NameDecoder.Instance);
FieldInfo field = actualType.GetField(name);
if (field != null)
{
object value = BsonSerializer.Deserialize(bsonReader, field.FieldType);
field.SetValue(obj, value);
}
break;
}
case BsonReaderState.Type:
{
bsonReader.ReadBsonType();
break;
}
case BsonReaderState.Value:
{
bsonReader.SkipValue();
break;
}
}
}
bsonReader.ReadEndDocument();
return (TValue)obj;
}
}
[StaticField]
private static readonly JsonWriterSettings defaultSettings = new() { OutputMode = JsonOutputMode.RelaxedExtendedJson };
public static void Register()
{
// 自动注册IgnoreExtraElements
ConventionPack conventionPack = new ConventionPack { new IgnoreExtraElementsConvention(true) };
ConventionRegistry.Register("IgnoreExtraElements", conventionPack, type => true);
RegisterStruct<float2>();
RegisterStruct<float3>();
RegisterStruct<float4>();
RegisterStruct<quaternion>();
RegisterStruct<FP>();
RegisterStruct<TSVector>();
RegisterStruct<TSVector2>();
RegisterStruct<TSVector4>();
RegisterStruct<TSQuaternion>();
Dictionary<string, Type> types = EventSystem.Instance.GetTypes();
foreach (Type type in types.Values)
{
if (!type.IsSubclassOf(typeof (Object)))
{
continue;
}
if (type.IsGenericType)
{
continue;
}
BsonClassMap.LookupClassMap(type);
}
}
public static void RegisterStruct<T>() where T : struct
{
BsonSerializer.RegisterSerializer(typeof (T), new StructBsonSerialize<T>());
}
public static string ToJson(object obj)
{
if (obj is ISupportInitialize supportInitialize)
{
supportInitialize.BeginInit();
}
return obj.ToJson(defaultSettings);
}
public static string ToJson(object obj, JsonWriterSettings settings)
{
if (obj is ISupportInitialize supportInitialize)
{
supportInitialize.BeginInit();
}
return obj.ToJson(settings);
}
public static T FromJson<T>(string str)
{
try
{
return BsonSerializer.Deserialize<T>(str);
}
catch (Exception e)
{
throw new Exception($"{str}\n{e}");
}
}
public static object FromJson(Type type, string str)
{
return BsonSerializer.Deserialize(str, type);
}
public static byte[] Serialize(object obj)
{
if (obj is ISupportInitialize supportInitialize)
{
supportInitialize.BeginInit();
}
return obj.ToBson();
}
public static void Serialize(object message, MemoryStream stream)
{
if (message is ISupportInitialize supportInitialize)
{
supportInitialize.BeginInit();
}
using (BsonBinaryWriter bsonWriter = new BsonBinaryWriter(stream, BsonBinaryWriterSettings.Defaults))
{
BsonSerializationContext context = BsonSerializationContext.CreateRoot(bsonWriter);
BsonSerializationArgs args = default;
args.NominalType = typeof (object);
IBsonSerializer serializer = BsonSerializer.LookupSerializer(args.NominalType);
serializer.Serialize(context, args, message);
}
}
public static object Deserialize(Type type, byte[] bytes)
{
try
{
return BsonSerializer.Deserialize(bytes, type);
}
catch (Exception e)
{
throw new Exception($"from bson error: {type.FullName} {bytes.Length}", e);
}
}
public static object Deserialize(Type type, byte[] bytes, int index, int count)
{
try
{
using (MemoryStream memoryStream = new MemoryStream(bytes, index, count))
{
return BsonSerializer.Deserialize(memoryStream, type);
}
}
catch (Exception e)
{
throw new Exception($"from bson error: {type.FullName} {bytes.Length} {index} {count}", e);
}
}
public static object Deserialize(Type type, Stream stream)
{
try
{
return BsonSerializer.Deserialize(stream, type);
}
catch (Exception e)
{
throw new Exception($"from bson error: {type.FullName} {stream.Position} {stream.Length}", e);
}
}
public static T Deserialize<T>(byte[] bytes)
{
try
{
using (MemoryStream memoryStream = new MemoryStream(bytes))
{
return (T)BsonSerializer.Deserialize(memoryStream, typeof (T));
}
}
catch (Exception e)
{
throw new Exception($"from bson error: {typeof (T).FullName} {bytes.Length}", e);
}
}
public static T Deserialize<T>(byte[] bytes, int index, int count)
{
return (T)Deserialize(typeof (T), bytes, index, count);
}
public static T Clone<T>(T t)
{
return Deserialize<T>(Serialize(t));
}
}
}