从Windows窗体控件复制粘贴到WPF控件时出现序列化错误(.NET5迁移后)
报错根本原因
程序集“System.Private.CoreLib, Version=5.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e”中的类型“System.RuntimeType”未标记为可序列化。
该报错由ClipboardDescriptor类中两个不符合.NET 5+序列化规则的成员触发:
System.Type类型的ObjType字段:.NET Framework中RuntimeType(Type的实际实现类)默认标记了可序列化,但.NET 5+重构了核心库实现,System.Private.CoreLib下的RuntimeType不再支持二进制序列化System.Windows.Forms.TreeNode类型的BaseTreeNode字段:WinForms控件本身的序列化逻辑不稳定,不适合跨UI框架(WinForms到WPF)传递
修复方案
方案1:替换不可序列化成员(推荐)
直接把不可序列化的字段替换为纯数据类型,避免框架兼容性问题:
- 将
System.Type ObjType替换为字符串类型的类型全名字段,需要使用类型时再通过反射动态加载 - 将
TreeNode BaseTreeNode替换为节点的唯一标识(如节点ID、名称、路径等),拖拽完成后在WPF端根据标识查找对应控件对象
修改后的类示例:
using System; namespace Support.Classes { /// <summary> /// ClipboardDescriptor的摘要说明 /// </summary> [Serializable] public class ClipboardDescriptor { private Guid id; private Guid parentDocumentID; // 替换Type为类型全名字符串 private string objTypeFullName; // 替换TreeNode为节点唯一标识 private string treeNodeUniqueKey; private string objname; public ClipboardDescriptor() { } public Guid ParentDocumentID { get { return parentDocumentID; } set { parentDocumentID = value; } } public Guid ID { get { return id; } set { id = value; } } public string ObjTypeFullName { get { return objTypeFullName; } set { objTypeFullName = value; } } // 辅助方法,需要使用Type时动态获取 public Type GetObjType() { return string.IsNullOrEmpty(objTypeFullName) ? null : Type.GetType(objTypeFullName); } public string ObjName { get { return objname; } set { objname = value; } } public string TreeNodeUniqueKey { get { return treeNodeUniqueKey; } set { treeNodeUniqueKey = value; } } } }
修改后原有拖拽代码var tClip = e.Data.GetDataPresent(typeof(ClipboardDescriptor));可正常运行。
方案2:自定义序列化逻辑
如果必须保留原有类的字段定义,可以实现ISerializable接口手动控制序列化过程:
using System; using System.Runtime.Serialization; using System.Windows.Forms; namespace Support.Classes { [Serializable] public class ClipboardDescriptor : ISerializable { private Guid id; private Guid parentDocumentID; private System.Type objtype; private TreeNode baseTreeNode; private string objname; public ClipboardDescriptor() { baseTreeNode = null; } // 反序列化构造函数 protected ClipboardDescriptor(SerializationInfo info, StreamingContext context) { id = (Guid)info.GetValue(nameof(ID), typeof(Guid)); parentDocumentID = (Guid)info.GetValue(nameof(ParentDocumentID), typeof(Guid)); objname = info.GetString(nameof(ObjName)); // 从序列化字符串中还原Type var typeName = info.GetString(nameof(objtype)); objtype = string.IsNullOrEmpty(typeName) ? null : Type.GetType(typeName); // TreeNode控件不序列化,反序列化后在目标端重新查找赋值 } // 自定义序列化逻辑 public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(ID), id); info.AddValue(nameof(ParentDocumentID), parentDocumentID); info.AddValue(nameof(ObjName), objname); // Type转为字符串存储 info.AddValue(nameof(objtype), objtype?.AssemblyQualifiedName); // 跳过TreeNode的序列化 } public Guid ParentDocumentID { get { return parentDocumentID; } set { parentDocumentID = value; } } public Guid ID { get { return id; } set { id = value; } } public System.Type ObjType { get { return objtype; } set { objtype = value; } } public string ObjName { get { return objname; } set { objname = value; } } public TreeNode BaseTreeNode { get { return baseTreeNode; } set { baseTreeNode = value; } } } }
内容的提问来源于stack exchange,提问作者James Ridley
相关产品推荐
相关产品推荐

