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

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];
}
}
}