using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.Eventing.Reader; using System.IO; using System.Linq; using System.Reflection; using System.Text; namespace BinarySerialize { public struct PropertyMetadata { public MemberInfo Info; public bool IsField; public Type Type; public uint rawTag; } public struct ArrayMetadata { private Type element_type; private bool is_array; private bool is_list; public Type ElementType { get { return element_type; } set { element_type = value; } } public bool IsArray { get { return is_array; } set { is_array = value; } } public bool IsList { get { return is_list; } set { is_list = value; } } } public struct ObjectMetadata { private Type element_type; private bool is_dictionary; private IDictionary properties; public IDictionary tag_type; public Type ElementType { get { return element_type; } set { element_type = value; } } public bool IsDictionary { get { return is_dictionary; } set { is_dictionary = value; } } public IDictionary Properties { get { return properties; } set { properties = value; } } } public static class Helper { //基础类型 public delegate void ExporterFunc(Stream stream,object obj,uint rawTag); public static IDictionary base_exporters_table = new Dictionary(); public delegate object ImporterFunc(Stream stream); public static IDictionary base_importers_table = new Dictionary(); //配置文件类型 public delegate object ConfigParseFunc(byte[] stream, int pos, byte[] strStream); public static IDictionary base_config_table = new Dictionary(); static Helper() { RegisterBaseExporters(); RegisterBaseImporters(); RegisterBaseConfig(); } private static void RegisterBaseConfig() { base_config_table[typeof(string)] = delegate (byte[] stream, int pos, byte[] strStream) { return ConfigParse.GetString(stream, pos, strStream); }; base_config_table[typeof(uint)] = delegate (byte[] stream, int pos, byte[] strStream) { return ConfigParse.GetUint(stream, pos); }; base_config_table[typeof(int)] = delegate (byte[] stream, int pos, byte[] strStream) { return ConfigParse.GetInt(stream, pos); }; base_config_table[typeof(long)] = delegate (byte[] stream, int pos, byte[] strStream) { return ConfigParse.GetLong(stream, pos); }; } private static void RegisterBaseExporters() { base_exporters_table[typeof(string)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteBytes(stream, Encoding.UTF8.GetBytes((string) obj)); }; base_exporters_table[typeof(Single)] = delegate (Stream stream, object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteFloat(stream,(float)obj); }; base_exporters_table[typeof(byte[])] = delegate (Stream stream, object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteBytes(stream, (byte[])obj); }; base_exporters_table[typeof(bool)] = delegate (Stream stream, object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteBool(stream,(bool)obj); }; base_exporters_table[typeof(float)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteFloat(stream, (float)obj); }; base_exporters_table[typeof(double)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteDouble(stream,(double)obj); }; base_exporters_table[typeof(short)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)(short)obj); }; base_exporters_table[typeof(ushort)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)(ushort)obj); }; base_exporters_table[typeof(int)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)(int)obj); }; base_exporters_table[typeof(uint)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)(uint)obj); }; base_exporters_table[typeof(long)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)(long)obj); }; base_exporters_table[typeof(ulong)] = delegate (Stream stream,object obj, uint rawTag) { if(rawTag>0)ProtocolParser.WriteUInt64(stream, (ulong)rawTag); ProtocolParser.WriteUInt64(stream, (ulong)obj); }; } private static void RegisterBaseImporters() { base_importers_table[typeof(string)] = delegate (Stream stream) { return ProtocolParser.ReadString(stream); }; base_importers_table[typeof(Single)] = delegate (Stream stream) { return ProtocolParser.ReadFloat(stream); }; base_importers_table[typeof(byte[])] = delegate (Stream stream) { return ProtocolParser.ReadBytes(stream); ; }; base_importers_table[typeof(Boolean)] = delegate (Stream stream) { return ProtocolParser.ReadBool(stream); }; base_importers_table[typeof(Int16)] = delegate (Stream stream) { return (Int16)ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(Int32)] = delegate (Stream stream) { return (Int32)ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(Int64)] = delegate (Stream stream) { return (Int64)ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(UInt16)] = delegate (Stream stream) { return (UInt16)ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(UInt32)] = delegate (Stream stream) { return (UInt32)ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(UInt64)] = delegate (Stream stream) { return ProtocolParser.ReadUInt64(stream); }; base_importers_table[typeof(Double)] = delegate (Stream stream) { return ProtocolParser.ReadDouble(stream); }; } //获取类型Type public static Type GetTypeByObject(object obj) { #if UNITY_2019_1_OR_NEWER if (obj is ILRuntime.Runtime.Intepreter.ILTypeInstance)//非基础类型 { return ((ILRuntime.Runtime.Intepreter.ILTypeInstance)obj).Type.ReflectionType; } else if (obj is ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType) { return ((ILRuntime.Runtime.Enviorment.CrossBindingAdaptorType)obj).ILInstance.Type.ReflectionType; } else #endif return obj.GetType(); } //获取实际类型type public static Type GetILRunTimeType(Type t) { #if UNITY_2019_1_OR_NEWER if (t is ILRuntime.Reflection.ILRuntimeWrapperType) { return ((ILRuntime.Reflection.ILRuntimeWrapperType) t).CLRType.TypeForCLR; //or return ((ILRuntime.Reflection.ILRuntimeWrapperType)t).RealType; } else #endif return t; } //ILRunTime运行时 public static IDictionary> type_properties = new Dictionary>(); private static readonly object type_properties_lock = new Object(); //导入类型 public static void AddTypeProperties(Type type) { if (type_properties.ContainsKey(type)) return; IList props = new List(); int index = 0; foreach (PropertyInfo p_info in type.GetProperties()) { if (p_info.Name == "Item") continue; index++; PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = p_info; p_data.IsField = false; p_data.Type = p_info.PropertyType; p_data.rawTag = GetRawTag(p_data, index); props.Add(p_data); } foreach (FieldInfo f_info in type.GetFields()) { index++; PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = f_info; p_data.IsField = true; p_data.Type = f_info.FieldType; p_data.rawTag = GetRawTag(p_data, index); props.Add(p_data); } lock (type_properties_lock) { try { type_properties.Add(type, props); } catch (ArgumentException) { return; } } } public static IDictionary array_metadata = new Dictionary(); private static readonly object array_metadata_lock = new Object(); public static void AddArrayMetadata(Type type) { if (array_metadata.ContainsKey(type)) return; ArrayMetadata data = new ArrayMetadata(); data.IsArray = type.IsArray; if (type.GetInterface("System.Collections.IList") != null) data.IsList = true; #if UNITY_2019_1_OR_NEWER if (type is ILRuntime.Reflection.ILRuntimeWrapperType) { var wt = (ILRuntime.Reflection.ILRuntimeWrapperType)type; if (data.IsArray) { data.ElementType = wt.CLRType.ElementType.ReflectionType; } else { data.ElementType = wt.CLRType.GenericArguments[0].Value.ReflectionType; } } else #endif { foreach (PropertyInfo p_info in type.GetProperties()) { if (p_info.Name != "Item") continue; ParameterInfo[] parameters = p_info.GetIndexParameters(); if (parameters.Length != 1) continue; if (parameters[0].ParameterType == typeof(int)) data.ElementType = p_info.PropertyType; } } lock (array_metadata_lock) { try { array_metadata.Add(type, data); } catch (ArgumentException) { return; } } } public static IDictionary object_metadata = new Dictionary(); private static readonly object object_metadata_lock = new Object(); public static void AddObjectMetadata(Type type) { if (object_metadata.ContainsKey(type)) return; ObjectMetadata data = new ObjectMetadata(); if (type.GetInterface("System.Collections.IDictionary") != null) data.IsDictionary = true; data.Properties = new Dictionary(); data.tag_type = new Dictionary(); int index = 0; foreach (PropertyInfo p_info in type.GetProperties()) { if (p_info.Name == "Item") { ParameterInfo[] parameters = p_info.GetIndexParameters(); if (parameters.Length != 1) continue; if (parameters[0].ParameterType == typeof(string)) { #if UNITY_2019_1_OR_NEWER if (type is ILRuntime.Reflection.ILRuntimeWrapperType) { data.ElementType = ((ILRuntime.Reflection.ILRuntimeWrapperType)type).CLRType.GenericArguments[1].Value.ReflectionType; } else #endif data.ElementType = p_info.PropertyType; } continue; } index++; PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = p_info; p_data.Type = p_info.PropertyType; data.Properties.Add(p_info.Name, p_data); data.tag_type.Add(GetTag(p_data,index), p_data); } foreach (FieldInfo f_info in type.GetFields()) { index++; PropertyMetadata p_data = new PropertyMetadata(); p_data.Info = f_info; p_data.IsField = true; p_data.Type = f_info.FieldType; data.Properties.Add(f_info.Name, p_data); data.tag_type.Add(GetTag(p_data, index), p_data); } lock (object_metadata_lock) { try { object_metadata.Add(type, data); } catch (ArgumentException) { return; } } } public static void ConcatByteArray(byte[] dest, int offset, byte[] source) { if (dest == null || offset < 0) { return; } if (source != null && dest.Length >= offset + source.Length) { for (int i = 0; i < source.Length; i++) { dest[i+ offset] = source[i]; } } } public static byte[] NewByteArray(int len) { return new byte[len]; } //protobuf 编码 //通过属性和字段获取proto tag public static uint GetTag(PropertyMetadata p_data, int index) { var tags = p_data.Info.GetCustomAttributes(false); if (tags == null || tags.Length == 0 || tags[0] == null) { //throw new Exception("GetProtoMemberAttribute 类型没有生成ProtoMemberAttribute:" + p_data.Info.Name); return (uint)index; } var attr = tags[0] as BinSerializeMemberAttribute; return (uint)attr.Tag; } public static uint GetRawTag(PropertyMetadata p_data,int index) { int tag = 0; var tags = p_data.Info.GetCustomAttributes(false); if (tags == null || tags.Length == 0 || tags[0] == null) { //throw new Exception("GetProtoMemberAttribute 类型没有生成ProtoMemberAttribute:" + p_data.Info.Name); tag = index; } else { var attr = tags[0] as BinSerializeMemberAttribute; tag = attr.Tag; } var type = p_data.Type; uint rawTag = 0; // if (type.IsGenericType && type.Name.Contains("List`1")) // { // type = GetGenericArgumentsType(p_data); // } if (type.IsClass || type.IsArray || type == typeof(string) || type.Name.Contains("List`1")) { rawTag = (uint)tag << 3 | (uint)Wire.LengthDelimited; } else if (type == typeof(double)) { rawTag = (uint)tag << 3 | (uint)Wire.Fixed64; } else if (type == typeof(float)) { rawTag = (uint)tag << 3 | (uint)Wire.Fixed32; } else { rawTag = (uint)tag << 3 | (uint)Wire.Varint; } return rawTag; } private static Type GetGenericArgumentsType(PropertyMetadata p_data) { if (p_data.Type.GenericTypeArguments.Length == 0) { throw new Exception("GetGenericArgumentsType 类型没有GenericTypeArguments:" + p_data.Info.Name); } return p_data.Type.GenericTypeArguments[0]; } } }