C#中如何无引用复制基类类型声明的派生类实例?
解决基类引用下派生类实例的通用克隆问题
你的核心问题在于反序列化时没有指定对象的实际派生类型,导致Json.NET只能创建基类ModelBase的实例,丢失了派生类的属性。这里有个直接且安全的解决方案,利用model.GetType()获取实际类型,再调用Json.NET的重载方法反序列化:
修改后的CloneModel方法
protected ModelBase CloneModel(ModelBase model) { if (model == null) return null; // 获取对象的实际派生类型(比如ModelUser) Type actualType = model.GetType(); string json = JsonConvert.SerializeObject(model); // 使用接受Type参数的反序列化重载,创建正确的派生类实例 return (ModelBase)JsonConvert.DeserializeObject(json, actualType); }
为什么之前的方法失败?
- 第一种尝试
JsonConvert.DeserializeObject<ModelBase>(json):泛型参数指定了基类,Json.NET只会解析ModelBase中定义的属性(也就是Status),完全忽略派生类的额外属性,最终得到的是纯ModelBase实例。 - 第二种尝试
JsonConvert.DeserializeObject<object>(json):当目标类型是object时,Json.NET默认会将JSON解析为JObject(它的动态JSON对象类型),而不是你期望的实体类实例,所以强转ModelBase会出错。
验证效果
在你的派生窗体FormMVBaseUser中,现在_originalModel的实际类型是ModelUser,可以安全访问派生类属性(建议先做类型检查避免异常):
private void button1_Click(object sender, EventArgs e) { if (_originalModel is ModelUser originalUser && model is ModelUser currentUser) { if (originalUser.UserFirst != currentUser.UserFirst) { // 执行相关操作 } } }
可选方案:利用TypeNameHandling(需注意安全)
如果你希望Json.NET自动处理类型信息,可以在序列化和反序列化时启用TypeNameHandling.Auto,这样JSON中会包含类型标识,反序列化时自动还原为正确的派生类:
protected ModelBase CloneModel(ModelBase model) { if (model == null) return null; var settings = new JsonSerializerSettings { TypeNameHandling = TypeNameHandling.Auto }; string json = JsonConvert.SerializeObject(model, settings); return (ModelBase)JsonConvert.DeserializeObject(json, settings); }
⚠️ 注意:如果你的程序会反序列化来自不可信来源的JSON,不建议使用TypeNameHandling,因为存在反序列化攻击的风险。直接使用GetType()的方法更安全,也更适配你的场景。
内容的提问来源于stack exchange,提问作者GuidoG
相关产品推荐
相关产品推荐

