MongoHelper.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Reflection;
  5. using MongoDB.Bson;
  6. using MongoDB.Bson.IO;
  7. using MongoDB.Bson.Serialization;
  8. using MongoDB.Bson.Serialization.Conventions;
  9. using MongoDB.Bson.Serialization.Serializers;
  10. using Unity.Mathematics;
  11. namespace ET
  12. {
  13. public static class MongoHelper
  14. {
  15. private class StructBsonSerialize<TValue>: StructSerializerBase<TValue> where TValue : struct
  16. {
  17. public override void Serialize(BsonSerializationContext context, BsonSerializationArgs args, TValue value)
  18. {
  19. Type nominalType = args.NominalType;
  20. IBsonWriter bsonWriter = context.Writer;
  21. bsonWriter.WriteStartDocument();
  22. FieldInfo[] fields = nominalType.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
  23. foreach (FieldInfo field in fields)
  24. {
  25. bsonWriter.WriteName(field.Name);
  26. BsonSerializer.Serialize(bsonWriter, field.FieldType, field.GetValue(value));
  27. }
  28. bsonWriter.WriteEndDocument();
  29. }
  30. public override TValue Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
  31. {
  32. //boxing is required for SetValue to work
  33. object obj = new TValue();
  34. Type actualType = args.NominalType;
  35. IBsonReader bsonReader = context.Reader;
  36. bsonReader.ReadStartDocument();
  37. while (bsonReader.State != BsonReaderState.EndOfDocument)
  38. {
  39. switch (bsonReader.State)
  40. {
  41. case BsonReaderState.Name:
  42. {
  43. string name = bsonReader.ReadName(Utf8NameDecoder.Instance);
  44. FieldInfo field = actualType.GetField(name);
  45. if (field != null)
  46. {
  47. object value = BsonSerializer.Deserialize(bsonReader, field.FieldType);
  48. field.SetValue(obj, value);
  49. }
  50. break;
  51. }
  52. case BsonReaderState.Type:
  53. {
  54. bsonReader.ReadBsonType();
  55. break;
  56. }
  57. case BsonReaderState.Value:
  58. {
  59. bsonReader.SkipValue();
  60. break;
  61. }
  62. }
  63. }
  64. bsonReader.ReadEndDocument();
  65. return (TValue)obj;
  66. }
  67. }
  68. [StaticField]
  69. private static readonly JsonWriterSettings defaultSettings = new() { OutputMode = JsonOutputMode.RelaxedExtendedJson };
  70. static MongoHelper()
  71. {
  72. // 自动注册IgnoreExtraElements
  73. ConventionPack conventionPack = new ConventionPack { new IgnoreExtraElementsConvention(true) };
  74. ConventionRegistry.Register("IgnoreExtraElements", conventionPack, type => true);
  75. RegisterStruct<float2>();
  76. RegisterStruct<float3>();
  77. RegisterStruct<float4>();
  78. RegisterStruct<quaternion>();
  79. Dictionary<string, Type> types = EventSystem.Instance.GetTypes();
  80. foreach (Type type in types.Values)
  81. {
  82. if (!type.IsSubclassOf(typeof (Object)))
  83. {
  84. continue;
  85. }
  86. if (type.IsGenericType)
  87. {
  88. continue;
  89. }
  90. //Log.Debug($"LookupClassMap: {type.Name}");
  91. BsonClassMap.LookupClassMap(type);
  92. }
  93. }
  94. public static void Init()
  95. {
  96. }
  97. public static void RegisterStruct<T>() where T : struct
  98. {
  99. BsonSerializer.RegisterSerializer(typeof (T), new StructBsonSerialize<T>());
  100. }
  101. public static string ToJson(object obj)
  102. {
  103. return obj.ToJson(defaultSettings);
  104. }
  105. public static string ToJson(object obj, JsonWriterSettings settings)
  106. {
  107. return obj.ToJson(settings);
  108. }
  109. public static T FromJson<T>(string str)
  110. {
  111. try
  112. {
  113. return BsonSerializer.Deserialize<T>(str);
  114. }
  115. catch (Exception e)
  116. {
  117. throw new Exception($"{str}\n{e}");
  118. }
  119. }
  120. public static object FromJson(Type type, string str)
  121. {
  122. return BsonSerializer.Deserialize(str, type);
  123. }
  124. public static byte[] Serialize(object obj)
  125. {
  126. return obj.ToBson();
  127. }
  128. public static void Serialize(object message, MemoryStream stream)
  129. {
  130. using (BsonBinaryWriter bsonWriter = new BsonBinaryWriter(stream, BsonBinaryWriterSettings.Defaults))
  131. {
  132. BsonSerializationContext context = BsonSerializationContext.CreateRoot(bsonWriter);
  133. BsonSerializationArgs args = default;
  134. args.NominalType = typeof (object);
  135. IBsonSerializer serializer = BsonSerializer.LookupSerializer(args.NominalType);
  136. serializer.Serialize(context, args, message);
  137. }
  138. }
  139. public static object Deserialize(Type type, byte[] bytes)
  140. {
  141. try
  142. {
  143. return BsonSerializer.Deserialize(bytes, type);
  144. }
  145. catch (Exception e)
  146. {
  147. throw new Exception($"from bson error: {type.Name}", e);
  148. }
  149. }
  150. public static object Deserialize(Type type, byte[] bytes, int index, int count)
  151. {
  152. try
  153. {
  154. using (MemoryStream memoryStream = new MemoryStream(bytes, index, count))
  155. {
  156. return BsonSerializer.Deserialize(memoryStream, type);
  157. }
  158. }
  159. catch (Exception e)
  160. {
  161. throw new Exception($"from bson error: {type.Name}", e);
  162. }
  163. }
  164. public static object Deserialize(Type type, Stream stream)
  165. {
  166. try
  167. {
  168. return BsonSerializer.Deserialize(stream, type);
  169. }
  170. catch (Exception e)
  171. {
  172. throw new Exception($"from bson error: {type.Name}", e);
  173. }
  174. }
  175. public static T Deserialize<T>(byte[] bytes)
  176. {
  177. try
  178. {
  179. using (MemoryStream memoryStream = new MemoryStream(bytes))
  180. {
  181. return (T)BsonSerializer.Deserialize(memoryStream, typeof (T));
  182. }
  183. }
  184. catch (Exception e)
  185. {
  186. throw new Exception($"from bson error: {typeof (T).Name}", e);
  187. }
  188. }
  189. public static T Deserialize<T>(byte[] bytes, int index, int count)
  190. {
  191. return (T)Deserialize(typeof (T), bytes, index, count);
  192. }
  193. public static T Clone<T>(T t)
  194. {
  195. return Deserialize<T>(Serialize(t));
  196. }
  197. }
  198. }