You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

2021年C#不可序列化对象深拷贝:无源码访问权限如何实现?

C# 无源码无序列化能力场景下的深拷贝实现方案

结论

可以实现。不需要修改目标对象源码,也不需要依赖序列化能力,核心实现思路基于反射+递归遍历+循环引用检测,可以覆盖所有访问修饰符的字段、跨程序集成员、多层嵌套引用场景。

核心实现步骤

  • 循环引用检测:提前定义全局字典Dictionary<object, object> _copiedObjects存储已拷贝的对象映射,键为原对象,值为已生成的拷贝对象,避免多层嵌套时出现循环引用导致无限递归,同时避免重复拷贝相同对象。
  • 实例化新对象:
    • 值类型和string类型直接返回原对象,无引用拷贝风险
    • 数组类型先创建相同长度、相同类型的新数组,后续递归拷贝每个元素
    • 普通引用类型用Activator.CreateInstance(type, true)调用无参构造创建实例,支持调用private修饰的构造函数
    • 遇到无无参构造函数的特殊类型,可改用FormatterServices.GetUninitializedObject(type)创建未初始化的对象,无需触发构造函数
      新实例创建完成后先存入_copiedObjects字典,再进行后续字段拷贝。
  • 全量字段拷贝:通过反射获取类型所有字段,绑定标志设置为BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy,可覆盖private、protected、internal修饰的所有实例字段,包括父类继承的非公开字段。遍历每个字段递归执行拷贝逻辑,再赋值给新实例对应字段。
  • 边界处理:委托类型可根据需求选择直接浅拷贝赋值或者置空;非托管指针类型需要结合实际业务场景判断是否需要额外拷贝逻辑。

核心代码示例

public static class DeepCopier
{
    private static readonly Dictionary<object, object> _copiedMap = new Dictionary<object, object>();

    public static T DeepCopy<T>(T original)
    {
        if (original == null) return default;
        Type type = original.GetType();

        // 处理值类型和字符串
        if (type.IsValueType || type == typeof(string))
        {
            return original;
        }

        // 已拷贝过的对象直接返回,避免循环引用
        if (_copiedMap.ContainsKey(original))
        {
            return (T)_copiedMap[original];
        }

        // 处理数组类型
        if (type.IsArray)
        {
            var elementType = type.GetElementType();
            var originalArr = original as Array;
            var newArr = Array.CreateInstance(elementType, originalArr.Length);
            _copiedMap.Add(original, newArr);
            for (int i = 0; i < originalArr.Length; i++)
            {
                newArr.SetValue(DeepCopy(originalArr.GetValue(i)), i);
            }
            return (T)(object)newArr;
        }

        // 创建普通引用类型实例
        object copy = Activator.CreateInstance(type, true);
        _copiedMap.Add(original, copy);

        // 拷贝所有访问级别的字段
        var fields = type.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy);
        foreach (var field in fields)
        {
            var fieldVal = field.GetValue(original);
            if (fieldVal == null)
            {
                field.SetValue(copy, null);
                continue;
            }
            field.SetValue(copy, DeepCopy(fieldVal));
        }

        // 清空映射字典,避免影响下次调用
        _copiedMap.Clear();
        return (T)copy;
    }
}

注意事项

  • 部分高权限限制的运行环境(如沙箱)可能会限制反射访问非公开成员,需提前确认运行环境权限。
  • 该方案性能略低于序列化方案,适合对性能要求不是极致苛刻的场景。

内容的提问来源于stack exchange,提问作者Beep13

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.07 14:18:00