MongoHelper.cs 7.8 KB

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