.NET 6替换BinaryFormatter实现对象克隆遇空值问题求助
.NET6 替代 BinaryFormatter 实现对象克隆的方案
问题根源
.NET6及后续版本默认禁用BinaryFormatter,核心原因是该组件存在严重安全风险,直接迁移原有代码必然触发报错。你用JsonSerializer克隆返回null,大概率是UserData类缺少公共无参构造函数、属性访问修饰符不符合序列化要求,或是未配置正确的序列化选项。
可靠替代方案
方案1:使用Newtonsoft.Json(JsonConvert)实现克隆
这是兼容性最稳定的方案,只要UserData类结构符合序列化规则就能正常工作,正确实现代码如下:
using Newtonsoft.Json; public class UserData { // 若存在自定义构造函数,必须显式声明无参构造函数;自动属性场景编译器会默认生成 public UserData() {} // 示例属性,替换为你的实际属性 public int Id { get; set; } public string Username { get; set; } public UserData Clone() { var jsonContent = JsonConvert.SerializeObject(this); return JsonConvert.DeserializeObject<UserData>(jsonContent); } } // 调用方式 var filteredData = records.Clone();
注意事项:
- 若
UserData包含嵌套类,嵌套类也需满足序列化要求(如无参构造函数、公共属性) - 私有属性需序列化时,添加
[JsonProperty]标记 - 存在循环引用时,需配置序列化选项:
JsonConvert.SerializeObject(this, new JsonSerializerSettings { ReferenceLoopHandling = ReferenceLoopHandling.Ignore })
方案2:修复System.Text.Json的实现
如果偏好官方的System.Text.Json,需针对性配置解决返回null的问题,代码示例:
using System.Text.Json; public class UserData { public UserData() {} public int Id { get; set; } public string Username { get; set; } public UserData Clone() { var serializeOptions = new JsonSerializerOptions { // 需序列化私有字段时开启 // IncludeFields = true, // 忽略循环引用 ReferenceHandler = ReferenceHandler.IgnoreCycles, // 确保反序列化兼容非无参构造函数场景 ConstructorHandling = JsonConstructorHandling.Default }; var jsonContent = JsonSerializer.Serialize(this, serializeOptions); return JsonSerializer.Deserialize<UserData>(jsonContent, serializeOptions); } }
若仍返回null,排查方向:
UserData是否有公共无参构造函数(System.Text.Json默认要求)- 属性是否为公共可读写类型
- 嵌套类型是否未配置序列化规则
方案3:手动实现克隆(性能最优)
对于结构简单的UserData,手动克隆是性能最高的方式,避免序列化/反序列化的额外开销:
public class UserData : ICloneable { public int Id { get; set; } public string Username { get; set; } // 引用类型属性需注意深克隆,避免浅拷贝导致原对象被修改 public UserProfile Profile { get; set; } public UserData Clone() { return new UserData { Id = this.Id, Username = this.Username, // 引用类型递归实现克隆 Profile = this.Profile?.Clone() }; } object ICloneable.Clone() { return Clone(); } } // 嵌套类同步实现克隆逻辑 public class UserProfile { public string Email { get; set; } public int Age { get; set; } public UserProfile Clone() { return new UserProfile { Email = this.Email, Age = this.Age }; } }
这种方式完全可控,无序列化开销,适合结构简单的对象场景。
方案4:使用映射库(复杂对象场景)
如果UserData结构复杂,不想手动编写克隆代码,可使用AutoMapper这类映射库:
// 全局初始化一次映射配置 var mapperConfig = new MapperConfiguration(cfg => cfg.CreateMap<UserData, UserData>()); var mapper = mapperConfig.CreateMapper(); public class UserData { // 你的属性... public UserData Clone() { return mapper.Map<UserData>(this); } }
AutoMapper会自动处理属性映射,支持复杂嵌套对象,配置完成后使用成本极低。
总结
- 追求简单稳定:优先选择Newtonsoft.Json(JsonConvert),兼容性覆盖绝大多数场景
- 偏好官方库:修复System.Text.Json的序列化配置,确保类符合序列化规则
- 性能敏感场景:手动实现克隆逻辑
- 复杂对象场景:使用AutoMapper等映射库减少重复代码
内容的提问来源于stack exchange,提问作者aman
相关产品推荐
相关产品推荐

