深度剖析:基于反射的.NET二进制序列化器设计与实现

🔍 深度剖析:基于反射的.NET二进制序列化器设计与实现

本文将从底层原理到高级优化,全面剖析一个基于反射的.NET二进制序列化器的设计与实现,涵盖类型系统处理、内存布局、递归算法、性能优化等核心主题。


1. 设计哲学与架构总览

1.1 核心设计理念

本文二进制序列化器的设计体现了几个核心原则:

  1. 通用性优先:通过反射机制处理任意.NET类型,无需预定义序列化契约
  2. 紧凑性优化:使用单字节长度前缀处理小型数据结构
  3. 类型驱动:严格依赖.NET类型系统进行序列化和反序列化
  4. 递归分解:将复杂对象分解为基本类型、字符串和集合
  5. 无元数据:序列化结果不包含类型信息,依赖反序列化时的类型上下文

1.2 整体架构图

是 否 是 否 是 否 是 否 是 否 是 否 序列化入口 类型识别引擎 值类型? 基本类型转换 字符串? 字符串编码 集合类型? 集合处理 对象属性递归 反序列化入口 类型识别引擎 值类型? 基本类型重建 字符串? 字符串解码 集合类型? 集合重建 对象属性递归 字节数组生成 对象重建 二进制输出 重建对象

1.3 核心模块分解

模块 功能 关键类/方法
类型识别 区分值类型/引用类型 GetSize(), ValueType列表
字节转换 类型到字节数组转换 GetBytes()系列方法
递归控制 对象树遍历 ToBytes(), ToObject()
集合处理 数组/列表处理 GetArrayElement(), CreateArrayCollection()
字符串编码 字符串序列化 GetBytes()字符串重载
对象构造 动态创建实例 Activator.CreateInstance()
API接口 公开序列化方法 Serialize(), Deserialize()

2. 类型系统深度解析

2.1 值类型处理机制

序列化器将.NET类型系统分为三类:

  1. 基本值类型:13种预定义数值类型+DateTime
  2. 字符串:特殊引用类型单独处理
  3. 其他引用类型:自定义对象和集合
2.1.1 值类型映射表
csharp 复制代码
private static IList<Type> ValueType = new Type[] { 
    typeof(double),   // 双精度浮点 8字节
    typeof(float),    // 单精度浮点 4字节
    typeof(long),     // 64位整数 8字节
    typeof(ulong),    // 64位无符号整数 8字节
    typeof(byte),     // 无符号字节 1字节
    typeof(sbyte),    // 有符号字节 1字节
    typeof(short),    // 16位整数 2字节
    typeof(ushort),   // 16位无符号整数 2字节
    typeof(char),     // Unicode字符 2字节
    typeof(int),      // 32位整数 4字节
    typeof(uint),     // 32位无符号整数 4字节
    typeof(bool),     // 布尔值 1字节 (0=false, 1=true)
    typeof(DateTime)  // 日期时间 (存储为Ticks) 8字节
};
2.1.2 特殊类型处理
  • DateTime :转换为long类型的Ticks存储
  • 浮点数 :使用BitConverter保证精度
  • bool:存储为单字节(0/1)

2.2 引用类型处理策略

引用类型分为三个子类:

  1. 字符串:长度前缀+UTF8内容
  2. 集合类型:元素数量前缀+递归元素
  3. 自定义对象:递归处理所有公共属性
2.2.1 集合类型识别算法
csharp 复制代码
private static Type GetArrayElement(Type array)
{
    // 处理数组类型 int[], string[] 等
    if (array.IsArray) 
        return array.GetElementType();
    
    // 处理泛型集合 List<T>, IList<T>
    if (array.IsGenericType && 
        (typeof(IList<>).GUID == array.GUID || 
         typeof(List<>).GUID == array.GUID))
    {
        Type[] args = array.GetGenericArguments();
        return args[0];
    }
    return null;
}
2.2.2 自定义对象处理原则
  • 仅处理公共属性(get/set)
  • 忽略字段、事件和方法
  • 属性顺序由反射返回顺序决定
  • 不支持循环引用(会导致栈溢出)

3. 序列化流程全链路剖析

3.1 序列化入口

csharp 复制代码
public static byte[] Serialize(object graph, Type type, bool single)
{
    // 参数校验
    if (graph == null) throw new ArgumentNullException("graph");
    if (type == null) throw new ArgumentNullException("type");
    
    // 核心序列化方法
    return GetBytes(type, graph, single);
}

3.2 类型分发器

csharp 复制代码
private static byte[] ToBytes(Type clazz, object value, bool single)
{
    using (MemoryStream ms = new MemoryStream())
    using (BinaryWriter sw = new BinaryWriter(ms))
    {
        int size = GetSize(clazz);
        
        // 值类型处理分支
        if (size > 0)
        {
            // 浮点数特殊处理
            if (clazz == typeof(double) || clazz == typeof(float))
            {
                sw.Write(GetBytes(clazz, value, size));
            }
            else
            {
                // DateTime转换为Ticks
                if (clazz == typeof(DateTime))
                    value = Convert.ToDateTime(value).Ticks;
                
                // 无符号长整型特殊处理
                if (clazz == typeof(ulong))
                    sw.Write(BitConverter.GetBytes(Convert.ToUInt64(value)));
                else
                    sw.Write(GetBytes(clazz, Convert.ToInt64(value), size));
            }
        }
        // 引用类型处理分支
        else
        {
            // 尝试作为字符串处理
            sw.Write(GetBytes(clazz, value != null ? 
                Convert.ToString(value) : null, single));
            
            // 尝试作为集合处理
            sw.Write(GetBytes(clazz, value as IList, single));
        }
        return ms.ToArray();
    }
}

3.3 对象递归序列化

csharp 复制代码
private static byte[] GetBytes(Type type, object value, bool single)
{
    using (MemoryStream ms = new MemoryStream())
    using (BinaryWriter sw = new BinaryWriter(ms))
    {
        // 遍历所有公共属性
        foreach (PropertyInfo prop in type.GetProperties())
        {
            // 获取属性值
            object propValue = prop.GetValue(value, null);
            
            // 递归序列化属性
            byte[] propData = ToBytes(prop.PropertyType, propValue, single);
            sw.Write(propData);
        }
        return ms.ToArray();
    }
}

3.4 集合序列化优化

csharp 复制代码
private static byte[] GetBytes(Type type, IList value, bool single)
{
    Type elementType = GetArrayElement(type);
    if (elementType != null)
    {
        using (MemoryStream ms = new MemoryStream())
        using (BinaryWriter sw = new BinaryWriter(ms))
        {
            if (value == null)
            {
                // null集合标记
                if (single) sw.Write((sbyte)-1);
                else sw.Write((short)-1);
            }
            else
            {
                int count = value.Count;
                // 写入元素数量
                if (single) 
                {
                    if (count > 255) throw new OverflowException("集合元素超过255");
                    sw.Write((byte)count);
                }
                else 
                {
                    if (count > 65535) throw new OverflowException("集合元素超过65535");
                    sw.Write((short)count);
                }
                
                // byte[]特殊优化
                if (type == typeof(byte[]))
                {
                    sw.Write((byte[])value);
                }
                else
                {
                    // 递归序列化每个元素
                    for (int i = 0; i < count; i++)
                    {
                        object item = value[i];
                        byte[] itemData = ToBytes(elementType, item, single);
                        sw.Write(itemData);
                    }
                }
            }
            return ms.ToArray();
        }
    }
    return new byte[0];
}

4. 反序列化流程全链路剖析

4.1 反序列化入口

csharp 复制代码
public static object Deserialize(byte[] buffer, Type type, bool single)
{
    if (buffer == null || type == null)
        throw new ArgumentNullException("buffer or type");
    
    using (MemoryStream ms = new MemoryStream(buffer))
    using (BinaryReader sr = new BinaryReader(ms))
    {
        ms.Seek(0, SeekOrigin.Begin);
        return GetObject(type, sr, single);
    }
}

4.2 类型分发器

csharp 复制代码
private static object ToObject(Type clazz, BinaryReader sr, bool single)
{
    int size = GetSize(clazz);
    
    // 值类型处理分支
    if (size > 0)
    {
        byte[] buffer = sr.ReadBytes(size);
        if (clazz == typeof(double) || clazz == typeof(float))
        {
            return GetValue(clazz, buffer, single);
        }
        else
        {
            if (clazz == typeof(DateTime))
            {
                object ticks = GetObject(typeof(long), buffer, size);
                return new DateTime(Convert.ToInt64(ticks));
            }
            return GetObject(clazz, buffer, size);
        }
    }
    // 引用类型处理分支
    else
    {
        if (clazz == typeof(string))
            return GetString(sr, single);
        else
            return GetList(clazz, sr, single);
    }
}

4.3 对象重建过程

csharp 复制代码
private static object GetObject(Type type, BinaryReader sr, bool single)
{
    // 创建对象实例
    object instance = Activator.CreateInstance(type);
    
    // 遍历所有属性
    foreach (PropertyInfo prop in type.GetProperties())
    {
        // 递归反序列化属性
        object value = ToObject(prop.PropertyType, sr, single);
        prop.SetValue(instance, value, null);
    }
    return instance;
}

4.4 集合重建算法

csharp 复制代码
private static object GetList(Type collectionType, BinaryReader reader, bool single)
{
    Type elementType = GetArrayElement(collectionType);
    if (elementType == null) return null;
    
    // 读取元素数量
    int length = single ? reader.ReadByte() : reader.ReadInt16();
    
    // 处理null集合
    if (single && (sbyte)length == -1) return null;
    if (length == -1) return null;
    
    // 创建空集合
    if (length <= 0) 
        return CreateArrayCollection(collectionType, elementType, 0);
    
    // byte[]特殊处理
    if (collectionType == typeof(byte[]))
        return reader.ReadBytes(length);
    
    // 创建集合实例
    IList collection = CreateArrayCollection(collectionType, elementType, length);
    
    for (int i = 0; i < length; i++)
    {
        object elementValue;
        
        // 值类型和字符串直接处理
        if (elementType.IsValueType || elementType == typeof(string))
            elementValue = ToObject(elementType, reader, single);
        else // 自定义对象递归处理
            elementValue = GetObject(elementType, reader, single);
        
        // 添加到集合
        if (collection.IsFixedSize) 
            collection[i] = elementValue;
        else 
            collection.Add(elementValue);
    }
    return collection;
}

5. 内存布局与二进制结构

5.1 整体二进制结构

复制代码
+----------------+----------------+----------------+----------------+
| 对象头(可选)   | 属性1数据      | 属性2数据      | ...            |
+----------------+----------------+----------------+----------------+

5.2 值类型存储格式

复制代码
+----------------+----------------+---+----------------+
| 字节0          | 字节1          |...| 字节n-1        |
+----------------+----------------+---+----------------+

5.3 字符串存储格式

复制代码
+----------------+----------------+----------------+
| 长度(1/2字节)  | 字符串内容     | 填充字节(可选) |
+----------------+----------------+----------------+

5.4 集合存储格式

复制代码
+----------------+----------------+----------------+----------------+
| 元素数量       | 元素1数据      | 元素2数据      | ...            |
+----------------+----------------+----------------+----------------+

5.5 自定义对象存储格式

复制代码
+----------------+----------------+----------------+----------------+
| 属性1数据      | 属性2数据      | 属性3数据      | ...            |
+----------------+----------------+----------------+----------------+

5.6 特殊标记

  • null字符串:长度=-1 (0xFF或0xFFFF)
  • null集合:元素数量=-1
  • 空字符串:长度=0

6. 递归算法与对象图处理

6.1 递归序列化算法

是 否 是 否 是 否 开始序列化对象 获取对象类型 是值类型? 转换为字节数组 是字符串? 写入长度+内容 是集合? 写入数量+递归元素 递归处理属性 结束

6.2 递归反序列化算法

是 否 是 否 是 否 开始反序列化 获取目标类型 是值类型? 读取字节并转换 是字符串? 读取长度+内容 是集合? 读取数量+递归元素 递归设置属性 结束

6.3 递归深度控制

当前实现没有递归深度控制,可能导致:

  • 栈溢出:深度对象图导致调用栈耗尽
  • 性能问题:深层递归效率低下

优化方案

csharp 复制代码
private const int MaxRecursionDepth = 100;
private static void SerializeObject(object obj, Type type, 
    BinaryWriter writer, bool single, int depth)
{
    if (depth > MaxRecursionDepth)
        throw new SerializationException("超出最大递归深度");
    
    // 递归处理属性...
    foreach (var prop in type.GetProperties())
    {
        SerializeValue(prop.GetValue(obj), prop.PropertyType, 
            writer, single, depth + 1);
    }
}

7. 集合类型特殊处理机制

7.1 集合类型识别

csharp 复制代码
private static Type GetArrayElement(Type collectionType)
{
    // 数组类型识别
    if (collectionType.IsArray)
        return collectionType.GetElementType();
    
    // 泛型集合识别
    if (collectionType.IsGenericType)
    {
        Type genericType = collectionType.GetGenericTypeDefinition();
        if (genericType == typeof(IList<>) || 
            genericType == typeof(List<>))
        {
            return collectionType.GetGenericArguments()[0];
        }
    }
    return null;
}

7.2 集合实例化

csharp 复制代码
private static IList CreateArrayCollection(Type collectionType, 
    Type elementType, int length)
{
    // 数组创建
    if (collectionType.IsArray)
        return Array.CreateInstance(elementType, length);
    
    // 泛型列表创建
    if (collectionType.IsGenericType)
    {
        Type genericDef = collectionType.GetGenericTypeDefinition();
        if (genericDef == typeof(IList<>) || 
            genericDef == typeof(List<>))
        {
            Type listType = typeof(List<>).MakeGenericType(elementType);
            ConstructorInfo ctor = listType.GetConstructor(new[] { typeof(int) });
            return (IList)ctor.Invoke(new object[] { length });
        }
    }
    return null;
}

7.3 特殊优化:byte[]

csharp 复制代码
if (type == typeof(byte[]))
{
    // 直接写入字节数组,避免递归处理
    sw.Write((byte[])value);
}
else
{
    // 递归处理每个元素
    for (int i = 0; i < value.Count; i++)
    {
        // ...
    }
}

8. 字符串编码与国际化

8.1 编码处理

csharp 复制代码
private static Encoding Encoding = Encoding.Default;

潜在问题

  • 跨平台兼容性:不同系统默认编码不同
  • 数据膨胀:非ASCII字符可能占用更多字节
  • 字符丢失:不支持的字符可能被替换

优化方案

csharp 复制代码
// 使用UTF-8作为统一编码
private static Encoding Encoding = Encoding.UTF8;

8.2 字符串序列化

csharp 复制代码
private static byte[] GetBytes(Type type, string value, bool single)
{
    if (type != typeof(string)) return new byte[0];
    
    using (MemoryStream ms = new MemoryStream())
    using (BinaryWriter sw = new BinaryWriter(ms))
    {
        if (value == null)
        {
            // null标记
            if (single) sw.Write((sbyte)-1);
            else sw.Write((short)-1);
        }
        else
        {
            byte[] data = Encoding.GetBytes(value);
            // 长度检查
            if (single && data.Length > 255)
                throw new ArgumentException("字符串超长");
            if (!single && data.Length > 65535)
                throw new ArgumentException("字符串超长");
            
            // 写入长度前缀
            if (single) sw.Write((byte)data.Length);
            else sw.Write((short)data.Length);
            
            // 写入内容
            sw.Write(data);
        }
        return ms.ToArray();
    }
}

8.3 字符串反序列化

csharp 复制代码
private static string GetString(BinaryReader reader, bool single)
{
    int length = single ? reader.ReadByte() : reader.ReadInt16();
    
    // 处理null
    if (single && (sbyte)length == -1) return null;
    if (length == -1) return null;
    
    // 空字符串
    if (length == 0) return string.Empty;
    
    // 读取内容并解码
    byte[] data = reader.ReadBytes(length);
    return Encoding.GetString(data);
}

9. 性能瓶颈与优化策略

9.1 性能热点分析

  1. 反射开销:反复获取类型信息
  2. 内存分配:频繁创建小对象
  3. 递归调用:深层次调用开销
  4. 装箱拆箱:值类型转换
  5. 流操作:小数据块频繁写入

9.2 优化方案

9.2.1 元数据缓存
csharp 复制代码
private static ConcurrentDictionary<Type, PropertyInfo[]> _propertyCache = 
    new ConcurrentDictionary<Type, PropertyInfo[]>();

private static PropertyInfo[] GetCachedProperties(Type type)
{
    return _propertyCache.GetOrAdd(type, t => t.GetProperties());
}
9.2.2 动态方法生成
csharp 复制代码
private static Func<object, object> CreatePropertyGetter(PropertyInfo prop)
{
    var objParam = Expression.Parameter(typeof(object), "obj");
    var access = Expression.Property(
        Expression.Convert(objParam, prop.DeclaringType), prop);
    return Expression.Lambda<Func<object, object>>(
        Expression.Convert(access, typeof(object)), objParam).Compile();
}

// 使用
var getter = CreatePropertyGetter(prop);
object value = getter(obj);
9.2.3 缓冲池技术
csharp 复制代码
private static readonly ObjectPool<MemoryStream> _streamPool = 
    new ObjectPool<MemoryStream>(() => new MemoryStream(), 10);

public static byte[] Serialize(object graph, bool single)
{
    MemoryStream ms = _streamPool.Get();
    try
    {
        // 使用ms序列化...
        return ms.ToArray();
    }
    finally
    {
        ms.SetLength(0); // 重置
        _streamPool.Return(ms);
    }
}
9.2.4 值类型特化
csharp 复制代码
private static void WriteValue(BinaryWriter writer, object value)
{
    switch (value)
    {
        case int i: writer.Write(i); break;
        case bool b: writer.Write(b); break;
        // ...其他类型
        default: 
            // 反射处理
            break;
    }
}

10. 完整代码逐行解析

csharp 复制代码
#pragma warning disable 0675 // 禁用特定编译器警告

namespace STDLOGIC_SERVER.Serialization
{
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Text;

    // 二进制序列化器静态类(分部类)
    public static partial class BinaryFormatter
    {
        // 预定义值类型列表(13种基本类型)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static readonly IList<Type> ValueType = new Type[] 
        { 
            typeof(double),   // 双精度浮点数,IEEE 754标准,8字节
            typeof(float),    // 单精度浮点数,IEEE 754标准,4字节
            typeof(long),     // 64位有符号整数,8字节
            typeof(ulong),    // 64位无符号整数,8字节
            typeof(byte),     // 8位无符号整数,1字节
            typeof(sbyte),    // 8位有符号整数,1字节
            typeof(short),    // 16位有符号整数,2字节
            typeof(ushort),   // 16位无符号整数,2字节
            typeof(char),     // UTF-16字符,2字节
            typeof(int),      // 32位有符号整数,4字节
            typeof(uint),     // 32位无符号整数,4字节
            typeof(bool),     // 布尔值,1字节(0=false, 非0=true)
            typeof(DateTime)  // 日期时间,存储为Ticks(100纳秒间隔),8字节
        };

        // 对应值类型的大小(字节数)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static readonly IList<byte> ValueSize = new byte[] 
        { 
            8,  // double
            4,  // float
            8,  // long
            8,  // ulong
            1,  // byte
            1,  // sbyte
            2,  // short
            2,  // ushort
            2,  // char
            4,  // int
            4,  // uint
            1,  // bool
            8   // DateTime
        };

        // 字符串编码方式(使用系统默认编码)
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private static Encoding Encoding = Encoding.Default;
    }

    // 序列化功能实现部分
    public static partial class BinaryFormatter
    {
        // 获取类型的字节大小(仅值类型)
        private static int GetSize(Type type)
        {
            // 在预定义值类型列表中查找索引
            int index = ValueType.IndexOf(type);
            // 非值类型返回0
            if (index < 0) return 0; 
            // 返回对应大小
            return ValueSize[index]; 
        }

        // 将数值转换为字节数组(通用方法)
        private static byte[] GetBytes(Type type, long value, int size = -1)
        {
            // 自动确定大小
            if (size < 0) size = GetSize(type);
            // 创建目标缓冲区
            byte[] buffer = new byte[size];
            
            // 使用非检查上下文避免溢出检查
            unchecked
            {
                // 小端序字节填充
                for (int i = 0; i < size; i++)
                {
                    // 每次右移8位并取最低字节
                    buffer[i] = (byte)((value >> (i * 8)) & 0xFF);
                }
            }
            return buffer;
        }

        // 字符串序列化方法
        private static byte[] GetBytes(Type type, string value, bool single)
        {
            // 仅处理字符串类型
            if (type != typeof(string)) return new byte[0];
            
            using (MemoryStream ms = new MemoryStream())
            using (BinaryWriter sw = new BinaryWriter(ms))
            {
                // 处理null字符串
                if (value == null) 
                {
                    // 根据长度模式写入-1标记
                    if (single) sw.Write((sbyte)-1);
                    else sw.Write((short)-1);
                }
                else
                {
                    // 获取字符串字节数据
                    byte[] data = Encoding.GetBytes(value);
                    
                    // 检查长度限制
                    if (single && data.Length > 255) 
                        throw new ArgumentException("字符串长度超过255");
                    if (!single && data.Length > 65535) 
                        throw new ArgumentException("字符串长度超过65535");
                    
                    // 写入长度前缀
                    if (single) sw.Write((byte)data.Length);
                    else sw.Write((short)data.Length);
                    
                    // 写入字符串内容
                    sw.Write(data);
                }
                return ms.ToArray();
            }
        }

        // 集合类型序列化方法
        private static byte[] GetBytes(Type type, IList value, bool single)
        {
            // 获取集合元素类型
            Type elementType = GetArrayElement(type);
            if (elementType == null) return new byte[0];
            
            using (MemoryStream ms = new MemoryStream())
            using (BinaryWriter sw = new BinaryWriter(ms))
            {
                // 处理null集合
                if (value == null) 
                {
                    if (single) sw.Write((sbyte)-1);
                    else sw.Write((short)-1);
                }
                else
                {
                    int count = value.Count;
                    // 检查长度限制
                    if (single && count > 255) 
                        throw new ArgumentException("集合元素超过255");
                    if (!single && count > 65535) 
                        throw new ArgumentException("集合元素超过65535");
                    
                    // 写入元素数量
                    if (single) sw.Write((byte)count);
                    else sw.Write((short)count);
                    
                    // byte[]特殊优化
                    if (type == typeof(byte[]))
                    {
                        sw.Write((byte[])value);
                    }
                    else
                    {
                        // 递归序列化每个元素
                        for (int i = 0; i < count; i++)
                        {
                            object item = value[i];
                            byte[] itemData = ToBytes(elementType, item, single);
                            sw.Write(itemData);
                        }
                    }
                }
                return ms.ToArray();
            }
        }

        // 自定义对象序列化方法
        private static byte[] GetBytes(Type type, object value, bool single)
        {
            using (MemoryStream ms = new MemoryStream())
            using (BinaryWriter sw = new BinaryWriter(ms))
            {
                // 遍历所有公共属性
                foreach (PropertyInfo prop in type.GetProperties())
                {
                    // 获取属性值
                    object propValue = prop.GetValue(value, null);
                    
                    // 递归序列化属性值
                    byte[] propData = ToBytes(prop.PropertyType, propValue, single);
                    sw.Write(propData);
                }
                return ms.ToArray();
            }
        }

        // 浮点数特殊处理方法(使用BitConverter)
        private static byte[] GetBytes(Type type, object value, int size)
        {
            // 单精度浮点处理
            if (type == typeof(float))
                return BitConverter.GetBytes(Convert.ToSingle(value));
            
            // 双精度浮点处理
            if (type == typeof(double))
                return BitConverter.GetBytes(Convert.ToDouble(value));
            
            return new byte[0];
        }

        // 类型分发序列化方法(核心)
        private static byte[] ToBytes(Type type, object value, bool single)
        {
            using (MemoryStream ms = new MemoryStream())
            using (BinaryWriter sw = new BinaryWriter(ms))
            {
                int size = GetSize(type);
                
                // 值类型处理分支
                if (size > 0)
                {
                    // 浮点数特殊处理
                    if (type == typeof(double) || type == typeof(float))
                    {
                        sw.Write(GetBytes(type, value, size));
                    }
                    else
                    {
                        // DateTime转换为Ticks
                        if (type == typeof(DateTime))
                        {
                            DateTime dt = Convert.ToDateTime(value);
                            value = dt.Ticks;
                        }
                        
                        // 无符号长整型特殊处理
                        if (type == typeof(ulong))
                        {
                            ulong ul = Convert.ToUInt64(value);
                            sw.Write(BitConverter.GetBytes(ul));
                        }
                        else
                        {
                            long longValue = Convert.ToInt64(value);
                            sw.Write(GetBytes(type, longValue, size));
                        }
                    }
                }
                // 引用类型处理分支
                else
                {
                    // 尝试序列化为字符串
                    sw.Write(GetBytes(type, value != null ? value.ToString() : null, single));
                    
                    // 尝试序列化为集合
                    sw.Write(GetBytes(type, value as IList, single));
                }
                return ms.ToArray();
            }
        }
    }

    // 集合类型辅助功能
    public static partial class BinaryFormatter
    {
        // 获取集合元素类型
        private static Type GetArrayElement(Type collectionType)
        {
            // 处理数组类型
            if (collectionType.IsArray)
                return collectionType.GetElementType();
            
            // 处理泛型集合
            if (collectionType.IsGenericType)
            {
                Type genericType = collectionType.GetGenericTypeDefinition();
                // 支持IList<T>和List<T>
                if (genericType == typeof(IList<>) || genericType == typeof(List<>))
                {
                    return collectionType.GetGenericArguments()[0];
                }
            }
            return null; // 非集合类型
        }

        // 创建集合实例
        private static IList CreateArrayCollection(Type collectionType, Type elementType, int length)
        {
            // 处理数组类型
            if (collectionType.IsArray)
                return Array.CreateInstance(elementType, length);
            
            // 处理泛型列表
            if (collectionType.IsGenericType)
            {
                Type genericDef = collectionType.GetGenericTypeDefinition();
                if (genericDef == typeof(IList<>) || genericDef == typeof(List<>))
                {
                    // 构造List<T>类型
                    Type listType = typeof(List<>).MakeGenericType(elementType);
                    // 获取带容量参数的构造函数
                    ConstructorInfo ctor = listType.GetConstructor(new Type[] { typeof(int) });
                    // 创建实例
                    return (IList)ctor.Invoke(new object[] { length });
                }
            }
            return null; // 不支持的类型
        }
    }

    // 反序列化功能实现
    public static partial class BinaryFormatter
    {
        // 将字节数据转换为特定类型的值
        private static object GetValue(Type type, long value)
        {
            // 在非检查上下文中处理转换
            unchecked
            {
                // 根据目标类型进行转换
                if (type == typeof(int))    return (int)value;
                if (type == typeof(uint))   return (uint)value;
                if (type == typeof(long))   return value;
                if (type == typeof(ulong))  return (ulong)value;
                if (type == typeof(bool))   return value != 0;
                if (type == typeof(byte))   return (byte)value;
                if (type == typeof(sbyte))  return (sbyte)value;
                if (type == typeof(short))  return (short)value;
                if (type == typeof(ushort)) return (ushort)value;
                return null; // 不支持的类型
            }
        }

        // 字符串反序列化
        private static string GetString(BinaryReader reader, bool single)
        {
            // 根据模式读取长度
            int length = single ? reader.ReadByte() : reader.ReadInt16();
            
            // 处理null值(-1标记)
            if (single && (sbyte)length == -1) return null;
            if (length == -1) return null;
            
            // 空字符串
            if (length == 0) return string.Empty;
            
            // 读取字符串内容
            byte[] data = reader.ReadBytes(length);
            return Encoding.GetString(data);
        }

        // 集合反序列化
        private static object GetList(Type collectionType, BinaryReader reader, bool single)
        {
            // 获取元素类型
            Type elementType = GetArrayElement(collectionType);
            if (elementType == null) return null;
            
            // 读取元素数量
            int length = single ? reader.ReadByte() : reader.ReadInt16();
            
            // 处理null集合
            if (single && (sbyte)length == -1) return null;
            if (length == -1) return null;
            
            // 创建空集合
            if (length <= 0) 
                return CreateArrayCollection(collectionType, elementType, 0);
            
            // byte[]特殊处理
            if (collectionType == typeof(byte[]))
                return reader.ReadBytes(length);
            
            // 创建集合实例
            IList collection = CreateArrayCollection(collectionType, elementType, length);
            
            // 读取每个元素
            for (int i = 0; i < length; i++)
            {
                object elementValue;
                
                // 值类型和字符串直接处理
                if (elementType.IsValueType || elementType == typeof(string))
                    elementValue = ToObject(elementType, reader, single);
                else // 自定义对象递归处理
                    elementValue = GetObject(elementType, reader, single);
                
                // 添加到集合
                if (collection.IsFixedSize) 
                    collection[i] = elementValue;
                else 
                    collection.Add(elementValue);
            }
            return collection;
        }

        // 字节数组转值类型
        private static object GetObject(Type type, byte[] buffer, int size = -1)
        {
            // 自动确定大小
            if (size < 0) size = GetSize(type);
            long value = 0;
            
            // 从小端序字节数组重建数值
            unchecked
            {
                for (int i = 0; i < size; i++)
                {
                    value |= ((long)buffer[i] & 0xFF) << (i * 8);
                }
            }
            return GetValue(type, value);
        }

        // 自定义对象反序列化
        private static object GetObject(Type type, BinaryReader reader, bool single)
        {
            // 创建对象实例(要求有无参数构造函数)
            object instance = Activator.CreateInstance(type);
            
            // 遍历所有属性
            foreach (PropertyInfo prop in type.GetProperties())
            {
                // 递归反序列化属性值
                object value = ToObject(prop.PropertyType, reader, single);
                prop.SetValue(instance, value, null);
            }
            return instance;
        }

        // 浮点数特殊处理
        private static object GetValue(Type type, byte[] buffer, bool single)
        {
            if (type == typeof(double))
                return BitConverter.ToDouble(buffer, 0);
            
            if (type == typeof(float))
                return BitConverter.ToSingle(buffer, 0);
            
            return null;
        }

        // 类型分发反序列化(核心)
        private static object ToObject(Type type, BinaryReader reader, bool single)
        {
            int size = GetSize(type);
            
            // 值类型处理分支
            if (size > 0)
            {
                byte[] buffer = reader.ReadBytes(size);
                
                // 浮点数特殊处理
                if (type == typeof(double) || type == typeof(float))
                    return GetValue(type, buffer, single);
                
                // DateTime特殊处理(从Ticks重建)
                if (type == typeof(DateTime))
                {
                    object ticks = GetObject(typeof(long), buffer, size);
                    return new DateTime(Convert.ToInt64(ticks));
                }
                
                // 其他值类型
                return GetObject(type, buffer, size);
            }
            // 引用类型处理分支
            else
            {
                if (type == typeof(string))
                    return GetString(reader, single);
                else
                    return GetList(type, reader, single);
            }
        }
    }

    // 公开API接口
    public static partial class BinaryFormatter
    {
        // 序列化对象(指定类型)
        public static byte[] Serialize(object graph, Type type, bool single)
        {
            if (graph == null) throw new ArgumentNullException("graph");
            if (type == null) throw new ArgumentNullException("type");
            return GetBytes(type, graph, single);
        }

        // 反序列化对象(指定类型)
        public static object Deserialize(byte[] buffer, Type type, bool single)
        {
            if (buffer == null) throw new ArgumentNullException("buffer");
            if (type == null) throw new ArgumentNullException("type");
            
            using (MemoryStream ms = new MemoryStream(buffer))
            using (BinaryReader reader = new BinaryReader(ms))
            {
                ms.Position = 0; // 重置流位置
                return GetObject(type, reader, single);
            }
        }

        // 泛型反序列化
        public static T Deserialize<T>(byte[] buffer, bool single)
        {
            object obj = Deserialize(buffer, typeof(T), single);
            return (obj == null) ? default : (T)obj;
        }

        // 序列化对象(自动获取类型)
        public static byte[] Serialize(object graph, bool single)
        {
            if (graph == null) throw new ArgumentNullException("graph");
            return Serialize(graph, graph.GetType(), single);
        }

        // 计算序列化后大小
        public static int SizeOf(object graph, bool single)
        {
            return (graph == null) ? 0 : Serialize(graph, single).Length;
        }
    }
}

11. 扩展性与应用场景

11.1 适用场景

  1. 游戏开发:网络消息传输
  2. 嵌入式系统:有限资源环境
  3. 配置文件:紧凑的二进制配置
  4. 数据存储:简单对象持久化
  5. RPC框架:轻量级远程调用

11.2 扩展方向

1.1 版本兼容性
csharp 复制代码
[SerializationVersion(1)]
public class MyClass
{
    [FieldOrder(1)]
    public int Field1;
    
    [FieldOrder(2), SinceVersion(2)]
    public string Field2;
}
1.2 循环引用支持

当前实现无法处理循环引用,遇到循环引用会导致无限递归和栈溢出。解决方案是引入对象引用跟踪机制。

1.3 序列化上下文设计
csharp 复制代码
private class SerializationContext
{
    public Dictionary<object, int> ObjectMap = new Dictionary<object, int>();
    public int NextId = 1;
}

private class DeserializationContext
{
    public Dictionary<int, object> ObjectMap = new Dictionary<int, object>();
}
1.4 序列化时处理引用
csharp 复制代码
private static byte[] ToBytes(Type type, object value, bool single, SerializationContext context)
{
    if (value == null)
    {
        // 写入null标记
        return new byte[] { 0xFF };
    }
    
    // 检查是否已序列化过
    if (context.ObjectMap.TryGetValue(value, out int id))
    {
        // 写入引用标记+ID
        return WriteReference(id);
    }
    
    // 首次遇到的对象
    id = context.NextId++;
    context.ObjectMap.Add(value, id);
    
    // 写入对象标记+ID
    byte[] header = WriteObjectHeader(id);
    byte[] data = SerializeObjectData(value, type, single, context);
    
    return CombineBytes(header, data);
}

private static byte[] WriteReference(int id)
{
    using (MemoryStream ms = new MemoryStream())
    using (BinaryWriter writer = new BinaryWriter(ms))
    {
        writer.Write((byte)0xFE); // 引用标记
        writer.Write(id);         // 对象ID
        return ms.ToArray();
    }
}

private static byte[] WriteObjectHeader(int id)
{
    using (MemoryStream ms = new MemoryStream())
    using (BinaryWriter writer = new BinaryWriter(ms))
    {
        writer.Write((byte)0xFD); // 对象标记
        writer.Write(id);         // 对象ID
        return ms.ToArray();
    }
}
1.5 反序列化时处理引用
csharp 复制代码
private static object ToObject(Type type, BinaryReader reader, bool single, DeserializationContext context)
{
    byte marker = reader.ReadByte();
    if (marker == 0xFF) return null; // null
    
    if (marker == 0xFE) // 引用
    {
        int id = reader.ReadInt32();
        return context.ObjectMap[id];
    }
    
    if (marker == 0xFD) // 新对象
    {
        int id = reader.ReadInt32();
        object obj = CreateObject(type, reader, single, context);
        context.ObjectMap.Add(id, obj);
        return obj;
    }
    
    // 其他处理...
}

2. 字段序列化支持

当前实现仅处理属性,可扩展支持字段序列化:

csharp 复制代码
private static IEnumerable<MemberInfo> GetSerializableMembers(Type type)
{
    // 获取所有公共字段和属性
    var fields = type.GetFields(BindingFlags.Public | BindingFlags.Instance);
    var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
        .Where(p => p.CanRead && p.CanWrite);
    
    return fields.Cast<MemberInfo>().Concat(properties);
}

3. 自定义序列化控制

通过特性控制序列化过程:

csharp 复制代码
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class NonSerializedAttribute : Attribute { }

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
public class SerializationOrderAttribute : Attribute
{
    public int Order { get; }
    public SerializationOrderAttribute(int order) => Order = order;
}

4. 流式序列化接口

支持大对象序列化到流,避免内存压力:

csharp 复制代码
public static void SerializeToStream(Stream stream, object graph, bool single)
{
    using (BinaryWriter writer = new BinaryWriter(stream, Encoding.Default, true))
    {
        SerializeToWriter(writer, graph, graph.GetType(), single);
    }
}

public static object DeserializeFromStream(Stream stream, Type type, bool single)
{
    using (BinaryReader reader = new BinaryReader(stream, Encoding.Default, true))
    {
        return DeserializeFromReader(reader, type, single);
    }
}

12. 总结与未来展望

12.1 技术总结

本文深入剖析了一个基于反射的.NET二进制序列化器的设计与实现,涵盖了:

  1. 类型系统处理机制(值类型/引用类型/集合)
  2. 递归序列化/反序列化算法
  3. 内存布局与二进制结构设计
  4. 字符串编码与集合处理优化
  5. 性能瓶颈分析与优化策略
  6. 扩展性设计与应用场景

12.2 优势与局限

优势

  • 无需预定义类型契约
  • 紧凑的二进制格式
  • 支持任意.NET类型
  • 简单易用的API

局限

  • 性能开销较大(反射)
  • 不支持循环引用
  • 无版本兼容机制
  • 安全性考虑不足

12.3 未来发展方向

  1. AOT编译支持:为Unity/IL2CPP环境提供支持
  2. Schema演进:支持向前/向后兼容
  3. 加密与签名:增加数据安全性
  4. 跨平台类型系统:支持多语言互操作
  5. 压缩支持:集成LZ4等压缩算法

通过深入理解这个序列化器的实现原理,开发者可以更好地设计适合特定场景的数据序列化方案,在性能、大小和灵活性之间找到最佳平衡点。