You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
536 lines
18 KiB
536 lines
18 KiB
|
|
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<string, PropertyMetadata> properties;
|
|
public IDictionary<uint, PropertyMetadata> 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<string, PropertyMetadata> Properties
|
|
{
|
|
get { return properties; }
|
|
set { properties = value; }
|
|
}
|
|
}
|
|
public static class Helper
|
|
{
|
|
//基础类型
|
|
public delegate void ExporterFunc(Stream stream,object obj,uint rawTag);
|
|
public static IDictionary<Type, ExporterFunc> base_exporters_table = new Dictionary<Type, ExporterFunc>();
|
|
|
|
public delegate object ImporterFunc(Stream stream);
|
|
public static IDictionary<Type, ImporterFunc> base_importers_table = new Dictionary<Type, ImporterFunc>();
|
|
|
|
//配置文件类型
|
|
public delegate object ConfigParseFunc(byte[] stream, int pos, byte[] strStream);
|
|
public static IDictionary<Type, ConfigParseFunc> base_config_table = new Dictionary<Type, ConfigParseFunc>();
|
|
|
|
|
|
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,IList<PropertyMetadata>> type_properties = new Dictionary<Type,IList<PropertyMetadata>>();
|
|
private static readonly object type_properties_lock = new Object();
|
|
//导入类型
|
|
public static void AddTypeProperties(Type type)
|
|
{
|
|
if (type_properties.ContainsKey(type))
|
|
return;
|
|
|
|
IList<PropertyMetadata> props = new List<PropertyMetadata>();
|
|
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<Type, ArrayMetadata> array_metadata = new Dictionary<Type, ArrayMetadata>();
|
|
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<Type, ObjectMetadata> object_metadata = new Dictionary<Type, ObjectMetadata>();
|
|
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<string, PropertyMetadata>();
|
|
data.tag_type = new Dictionary<uint, PropertyMetadata>();
|
|
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];
|
|
}
|
|
|
|
}
|
|
}
|
|
|