#if UNITY_2019_1_OR_NEWER using ILRuntime.CLR.Method; using ILRuntime.CLR.Utils; using ILRuntime.Runtime.Intepreter; using ILRuntime.Runtime.Stack; #endif using System; using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace BinarySerialize { public static class BinSerialize { #region Serialize public static void Serialize(Stream stream,object param,uint rawTag) { if (param != null) { Type type = Helper.GetTypeByObject(param); if (true /*rawTag > 0*/) { type = Helper.GetILRunTimeType(type); if (Helper.base_exporters_table.ContainsKey(type)) { Helper.base_exporters_table[type](stream, param, rawTag); } else if (param is Enum) { var enumValType = Enum.GetUnderlyingType(type); if (Helper.base_exporters_table.ContainsKey(enumValType)) { Helper.base_exporters_table[enumValType](stream, param, rawTag); } } else { if (type.IsGenericType || type.IsArray) { //if (param is IDictionary) 暂时不支持map //SerializeDic(stream,(System.Collections.IDictionary)param, type, rawTag); //else if (param is IList || /*type.Name.Contains("Stack`1") || type.Name.Contains("Queue`1") ||*/ type.IsArray) SerializeList(stream, (System.Collections.IEnumerable)param, type, rawTag); else throw new Exception("Serialize.serialize 未定义的类型1:" + type.ToString()); } else if (type.IsClass) { Helper.AddTypeProperties(type); if (rawTag > 0) { ProtocolParser.WriteUInt64(stream, (ulong)rawTag); } var msField = new MemoryStream(); msField.SetLength(0); SerializeClass(msField, param, type); uint length11 = (uint)msField.Length; ProtocolParser.WriteUInt32(stream, length11); msField.WriteTo(stream); } else { throw new Exception("Serialize.serialize 未定义的类型2:" + type.ToString()); } } } else { throw new Exception("Serialize.serialize rawTag error::" + type.ToString()); } } } private static void SerializeClass(Stream stream,object obj, Type type) { if (obj == null) return; Helper.AddTypeProperties(type); IList props = Helper.type_properties[type]; foreach (PropertyMetadata p_data in props) { if (p_data.IsField) { Serialize(stream,((FieldInfo) p_data.Info).GetValue(obj), p_data.rawTag); } else { PropertyInfo p_info = (PropertyInfo)p_data.Info; if (p_info.CanRead) { Serialize(stream,p_info.GetValue(obj, null), p_data.rawTag); } } } } private static void SerializeList(Stream stream,System.Collections.IEnumerable param,Type type,uint rawTag) { if (param != null) { Helper.AddArrayMetadata(type); ArrayMetadata t_data = Helper.array_metadata[type]; Type elem_type; if (!t_data.IsArray && !t_data.IsList) { throw new Exception(string.Format("Type {0} can't act as an array", type)); } if (!t_data.IsArray) { elem_type = t_data.ElementType; } else { elem_type = type.GetElementType(); } if (!elem_type.IsClass)//元素不是类类型 { ProtocolParser.WriteUInt32(stream,rawTag); var msField = new MemoryStream(); msField.SetLength(0); foreach (var item in param) { Serialize(msField, item, 0); } uint length11 = (uint)msField.Length; ProtocolParser.WriteUInt32(stream, length11); msField.WriteTo(stream); } else { foreach (var item in param) { Serialize(stream, item, rawTag); } } } return; } public static byte[] Serialize(object obj) { if (obj != null) { MemoryStream stream = new MemoryStream(); var type = Helper.GetTypeByObject(obj); SerializeClass(stream, obj, type); return stream.ToArray(); } return null; } #endregion #region Deserialize public static T Deserialize(byte[] arr) { //PositionStream stream = new PositionStream(arr); MemoryStream stream = new MemoryStream(arr); return (T)DeserializeClass(typeof(T), stream); } private static object Deserialize(Stream stream,Type type) { object obj = null; type = Helper.GetILRunTimeType(type); if (Helper.base_importers_table.ContainsKey(type)) { obj = Helper.base_importers_table[type](stream); } else if (type.BaseType == typeof(Enum)) { var numType = Helper.GetILRunTimeType(Enum.GetUnderlyingType(type)); if (Helper.base_importers_table.ContainsKey(numType)) { obj = Helper.base_importers_table[numType](stream); } } else if (type.IsGenericType || type.IsClass || type.IsArray) { if (type.Name.Contains("List`1")) { //obj = DeserializeList(type, stream); throw new Exception("Serialize.Deserialize 未定义的类型:" + type.ToString()); } /*else if (type.Name.Contains("Dictionary`2")) { obj = DeserializeDic(type, stream); } else if (type.Name.Contains("Queue`1")) { obj = DeserializeQueue(type, data); } else if (type.Name.Contains("Stack`1")) { obj = DeserializeStack(type, data); }*/ else if (type.IsClass) { long limit = ProtocolParser.ReadUInt32(stream); obj = DeserializeClass(type, stream, limit); } else { throw new Exception("Serialize.Deserialize 未定义的类型:" + type.ToString()); } } else { throw new Exception("Serialize.Deserialize 未定义的类型:" + type.ToString()); } return obj; } public static object DeserializeClass(Type type, Stream stream, long limit = -1) { object instance = null; Helper.AddObjectMetadata(type); ObjectMetadata t_data = Helper.object_metadata[type]; #if UNITY_2019_1_OR_NEWER if (type is ILRuntime.Reflection.ILRuntimeType) instance = ((ILRuntime.Reflection.ILRuntimeType)type).ILType.Instantiate(); else instance = Activator.CreateInstance(type); #else instance = Activator.CreateInstance(type); #endif Dictionary object_list = new Dictionary(); Dictionary object_type = new Dictionary(); ObjectMetadata props = Helper.object_metadata[type]; limit += stream.Position; while (true) { if (limit > 0 && stream.Position >= limit) { if (stream.Position == limit) break; else throw new ProtocolBufferException("Read past max limit"); } int keyByte = stream.ReadByte(); if (keyByte == -1) break; var key = ProtocolParser.ReadKey((byte)keyByte, stream); var tag = key.Field; if (tag == 0) { if (limit > 0) { ProtocolParser.SkipKey(stream, key); continue; } else { break; } } if (props.tag_type.ContainsKey(tag)) { bool isList = false; var v = props.tag_type[tag]; if (v.Type.IsGenericType && v.Type.Name.Contains("List`1"))//list { Type elementType = null; IList list = null; if (!object_list.ContainsKey(tag)) { elementType = typeof(int); list = CreateIListByType(v.Type, ref elementType); object_list.Add(tag, list); object_type.Add(tag,elementType); } list = object_list[tag]; elementType = object_type[tag]; //版本问题,List 作为 Wire.LengthDelimited 成为数组 if (!elementType.IsClass && key.WireType == Wire.LengthDelimited) { long length = ProtocolParser.ReadUInt32(stream) + stream.Position; while (true) { if (stream.Position >= length) { if (stream.Position == length) break; else throw new ProtocolBufferException("Read past max limit list"); } DeserializeList(stream, ref list, ref elementType); } } else { DeserializeList(stream, ref list, ref elementType); } } else { if (v.IsField) { var info = (FieldInfo)v.Info; var num = Deserialize(stream, v.Type); info.SetValue(instance, num); } else { PropertyInfo p_info = (PropertyInfo)v.Info; if (p_info.CanRead) { var num = Deserialize(stream, v.Type); if (p_info.CanWrite) { p_info.SetValue(instance, num); } } } } } else { throw new ProtocolBufferException("something went wrong in the stream,Invalid tag: "+tag); } } foreach (var v in object_list) { var tag = v.Key; var t = props.tag_type[tag]; if (t.IsField) { ((FieldInfo)t.Info).SetValue(instance, v.Value); } else { PropertyInfo p_info = (PropertyInfo)t.Info; if (p_info.CanWrite) { p_info.SetValue(instance, v.Value); } } } return instance; } private static IList CreateIListByType(Type type, ref Type elem_type) { IList list = null; Helper.AddArrayMetadata(type); ArrayMetadata t_data = Helper.array_metadata[type]; if (!t_data.IsArray && !t_data.IsList) { throw new Exception(string.Format("Type {0} can't act as an array", type)); } if (!t_data.IsArray) { list = (IList)Activator.CreateInstance(type); elem_type = t_data.ElementType; } else { list = new ArrayList(); elem_type = type.GetElementType(); } return list; } private static void DeserializeList(Stream stream,ref IList list, ref Type elem_type) { var rt = Helper.GetILRunTimeType(elem_type); var item = Deserialize(stream, rt); #if UNITY_2019_1_OR_NEWER if (elem_type is ILRuntime.Reflection.ILRuntimeType && ((ILRuntime.Reflection.ILRuntimeType)elem_type).ILType.IsEnum) { item = (int)item; } else { item = rt.CheckCLRTypes(item); } #else if (elem_type.BaseType == typeof(Enum)) { item = (int) item; } #endif list.Add(item); return; } #endregion #if UNITY_2019_1_OR_NEWER public unsafe static void RegisterILRuntimeCLRRedirection(ILRuntime.Runtime.Enviorment.AppDomain appdomain) { foreach (var i in typeof(BinSerialize).GetMethods()) { if (i.Name == "Deserialize" && i.IsGenericMethodDefinition)//泛型需要注册 { var param = i.GetParameters(); if (param[0].ParameterType == typeof(byte[])) { appdomain.RegisterCLRMethodRedirection(i, ByteToObject); } } } } public unsafe static StackObject* ByteToObject(ILIntepreter intp, StackObject* esp, IList mStack, CLRMethod method, bool isNewObj) { ILRuntime.Runtime.Enviorment.AppDomain __domain = intp.AppDomain; StackObject* ptr_of_this_method; StackObject* __ret = ILIntepreter.Minus(esp, 1); ptr_of_this_method = ILIntepreter.Minus(esp, 1); byte[] json = (byte[])typeof(byte[]).CheckCLRTypes(StackObject.ToObject(ptr_of_this_method, __domain, mStack)); intp.Free(ptr_of_this_method); var type = method.GenericArguments[0].ReflectionType; MemoryStream stream = new MemoryStream(json); var result_of_this_method = DeserializeClass(type, stream); return ILIntepreter.PushObject(__ret, mStack, result_of_this_method); } #endif } }