【Syncfusion系列】Diagram 杂谈 第三篇 序列化和反序列化
目录
- 序列化
- 保存
- C# 代码示例, 方式1 :
- C# 代码示例, 方式2 :
- 反序列化
- 加载
- C# 代码示例, 方式1:
- C# 代码示例, 方式2:
- **如何序列化自定义属性**
- 序列化和反序列化都存在的一个问题
- 解决方式
- 图表是否已修改?
- 如何在新版本中加载SfDiagram的旧版本
序列化
序列化是将SfDiagram对象的状态转换为字节流的过程,以便在需要时重新创建它们。这样的流可以存储在数据库中、作为文件或内存中。相反的过程称为反序列化。
保存
在SfDiagram中,使用DataContractSerializer进行序列化。DataContractSerializer的功能适用于SfDiagram序列化。它支持将SfDiagram保存到流中。SfDiagram会连同其所有属性一起被保存。
C# 代码示例, 方式1 :
// 将文件保存为流
SaveFileDialog dialog = new SaveFileDialog();
dialog.Title = "保存XAML";
dialog.Filter = "XAML文件(*.xaml)|*.xaml";
if (dialog.ShowDialog() == true)
{using (Stream str = File.Open(dialog.FileName, FileMode.CreateNew)){sfDiagram.Save(str);}
}
C# 代码示例, 方式2 :
// 将保存为内存流(FileMode.Create 会覆盖已有的,FileMode.CreateNew 不会覆盖已有的)using (Stream str = File.Open(GlobalData.Instance.WfFullName, FileMode.Create)){diagram.Save(str);}
反序列化
加载
在反序列化过程中,使用保存的流来加载当前视图中的SfDiagram节点和连接器。通过这种方式,你可以通过加载适当的流继续处理之前保存的SfDiagram。
C# 代码示例, 方式1:
// 从保存的XAML文件中加载
OpenFileDialog dialog = new OpenFileDialog();
if (dialog.ShowDialog() == true)
{using (Stream myStream = dialog.OpenFile()){sfDiagram.Load(myStream);}
}
C# 代码示例, 方式2:
// 从保存的内存流中加载
using (FileStream fileStream = new FileStream(FullName, FileMode.Open, FileAccess.Read))
{diagram.Load(fileStream);
}
如何序列化自定义属性
在SfDiagram中,你不能序列化每个图表对象的Content和ContentTemplate。如果你想保留图表对象的ContentTemplate,请将它们保存在资源中,并在图表对象添加到图表页面后应用它们。
自定义类中的自定义属性,如果从SfDiagram的任何接口或任何视图模型类派生,则可以通过DataMember属性进行序列化。
C# 代码示例:
public class NodeContent : INode
{[DataMember]public string NodeType{get;set;}
}
也就是说,只要你添加了[DataMember]特性,你自己添加的属性也会被序列化!
但前提是,你的这个类是从SfDiagram的接口或任何视图模型类派生的。
注意
SfDiagram的接口和视图模型类是在没有DataContract属性的情况下创建的。因此,对于从这些类派生的类,你不需要添加DataContract属性。
如何序列化自定义类
您可以借助 DataContract 属性和 SfDiagram 的 KnownTypes 属性来序列化业务类。您必须添加 DataContract 属性来序列化整个类。
(再说一次人话): 在进行序列化操作时,如果你有一个业务类(business class),并且这个类没有从任何已经标记了DataContract属性的基类(base class)继承,那么你需要给这个类添加DataContract属性来序列化整个类。简而言之,如果一个类没有继承自一个已经定义了DataContract属性的基类,那么你需要为这个类本身添加DataContract属性,以便能够对其进行序列化。
C# 代码示例:
[DataContract]
public class NodeContent
{[DataMember]public string NodeType{get;set;}
}Diagram.KnownTypes = () => new List<Type>()
{typeof(NodeContent)
};
序列化和反序列化都存在的一个问题
我自己定义一个继承自SfDiagram的接口和视图模型类的类
public class VisualNode : BpmnNodeViewModel
{[DataMember]public string? IDString { get; set; } = null;/// <summary>/// 为view窗口名称,用于打开对于节点窗口!/// </summary>[DataMember]public string NodeViewType { get; set; } = "Activity";/// <summary>/// 工作流节点类型/// </summary>[DataMember]public string StepType { get; set; } = "";/// <summary>/// 记录输入参数(为了方便Diagram自带的序列化可以进行,这里需要改为string类型)/// </summary>[DataMember]public JObject Inputs { get; set; } = null;/// <summary>/// 记录输出参数(为了方便Diagram自带的序列化可以进行,这里需要改为string类型)/// </summary>[DataMember]public JObject Outputs { get; set; } = null;
}
在C#中使用序列化时,如果遇到System.Runtime.Serialization.InvalidDataContractException
错误,特别是涉及到Newtonsoft.Json.Linq.JToken
类型时,通常是因为JToken
类型是一个递归集合数据
,这在序列化过程中不被支持。错误信息提示:“Type ‘Newtonsoft.Json.Linq.JToken’ is a recursive collection data contract which is not supported. Consider modifying the definition of collection ‘Newtonsoft.Json.Linq.JToken’ to remove references to itself.”。
JToken
(包括JObject
和JArray
)由于其设计为可以包含自身类型的实例(例如,一个JObject
可以包含另一个JObject
作为其属性值),导致了递归定义,这在数据契约序列化中是不被允许的。
解决方式
将他们改成string 格式!
/// </summary>[DataMember]public string Inputs { get; set; } = "{}";/// <summary>/// 记录输出参数(为了方便Diagram自带的序列化可以进行,这里需要改为string类型)/// </summary>[DataMember]public string Outputs { get; set; } = "{}";
JObject 存的时候先序列化
node.Outputs = JsonConvert.SerializeObject(obj);
JObject 用的时候,再反序列化即可
jsonStepData.Outputs = JsonConvert.DeserializeObject<JObject>(FirstFuncNode.Outputs);
图表是否已修改?
图表控件的HasChanges属性用于通知图表是否有未保存的更改。该属性跟踪通过交互和公共API所做的所有更改。
XAML 代码示例:
<!-- 初始化图表 -->
<Syncfusion:SfDiagram x:Name="diagram">
</Syncfusion:SfDiagram>
<!-- 初始化保存图表的按钮 -->
<Button x:Name="SaveButton" Content="保存" Click="SaveButton_Click">
</Button>
//Method to promote the save dialouge box when diagram has any unsaved changes.
private void SaveButton_Click(object sender, RoutedEventArgs e)
{if (diagram != null && diagram.HasChanges){MessageBoxResult messageBoxResult = MessageBox.Show("Do you want to save the Diagram?","SfDiagram",MessageBoxButton.YesNo);if (messageBoxResult == MessageBoxResult.Yes){SaveDiagram();}}
}//Method to save the diagram.
private void SaveDiagram()
{SaveFileDialog dialog = new SaveFileDialog();dialog.Title = "Save XAML";dialog.Filter = "XAML File (*.xaml)|*.xaml";if (dialog.ShowDialog() == true){File.Delete(dialog.FileName);using (Stream s = File.Open(dialog.FileName, FileMode.OpenOrCreate)){diagram.Save(s);}}
}
如何在新版本中加载SfDiagram的旧版本
你可以通过升级方法在新版本中加载任何旧版本的SfDiagram流。请参考以下代码示例。
C# 代码示例:
using (Stream myStream = dialog.OpenFile())
{sfDiagram.Upgrade(myStream);sfDiagram.Load(myStream);
}
相关文章:
【Syncfusion系列】Diagram 杂谈 第三篇 序列化和反序列化
目录 序列化保存C# 代码示例, 方式1 :C# 代码示例, 方式2 : 反序列化加载C# 代码示例, 方式1:C# 代码示例, 方式2: **如何序列化自定义属性**序列化和反序列化都存在的一个问题解决方式 图表是否已修改&…...

Apache APISIX快速入门
本文将介绍Apache APISIX,这是一个开源API网关,可以处理速率限制选项,并且可以轻松地完全控制外部流量对内部后端API服务的访问。我们将看看是什么使它从其他网关服务中脱颖而出。我们还将详细讨论如何开始使用Apache APISIX网关。 在深入讨…...

【经典】制造供应链四类策略(MTS、MTO、ATO、ETO)细说
关注作者 制造供应链的牛鞭问题与复杂问题主要是从两个方面解决,一是同步化供应链消减从需求到供应的放大效应,二是供应链细分,针对不同的客户、不同的需求供应的匹配策略来应对复杂性,更好的满足客户并以最低的总成本来实现。 对…...

基于stm32的红外测温系统设计(论文+源码)
1总体方案设计 本课题为基于STM32的红外测温系统设计,在此将系统架构设计如图3.1所示, 整个系统包括STM32F103单片机,红外测温模块MLX90614,显示模块OLED12864,蜂鸣器以及按键等构成,在功能上,…...
前端WebSocket应用——聊天实时通信的基本配置
使用 WebSocket 实现实时通信的 Vue 应用 前言1. WebSocketService 类 1.1 类属性1.2 构造函数和连接初始化1.3 WebSocket 连接1.4 事件处理方法1.5 发送和关闭 WebSocket 消息1.6 状态查询与回调注册1.7 完整代码 2. 在 Vue 组件中使用 WebSocketService 2.1 定义 WebSocket …...

博弈论1:拿走游戏(take-away game)
假设你和小红打赌,玩“拿走游戏”,输的人请对方吃饭.... 你们面前有21个筹码,放成一堆;每轮你或者小红可以从筹码堆中拿走1个/2个/3个;第一轮你先拿,第二轮小红拿,你们两个人交替进行;拿走筹码堆…...
Debezium OracleValueConverters 分析
Debezium OracleValueConverters 分析 目录 1. 概述2. 核心功能3. 数据类型映射4. 特殊场景处理5. 最佳实践6. 使用示例7. 常见问题8. 扩展建议9. 总结1. 概述 OracleValueConverters 是 Debezium Oracle 连接器中负责数据类型转换的核心类,它继承自 JdbcValueConverters。主…...

WPF 消息循环(二)
们已经知道,win32/MFC/WinForm/WPF 都依靠消息循环驱动,让程序跑起来。 这里就介绍 WPF 中是如何使用消息循环来驱动程序的。 1. 背景 只听说过 Dispatcher ,哪里来的消息循环? WPF 启动运行堆栈: > WpfApp1.…...

ubuntu上更改ext4格式的硬盘为 windows的 NTFS 格式参考
1. ubuntu上安装 sudo apt-get install gparted 2. 参考如下,下面是转换后的样例。 3.windows上添加识别新硬盘参考 先在设备管理器中 找到下面 磁盘管理 如下:找到类似下面的磁盘2 查看相关信息 右键可以新建卷和格式化,下面是已经新建…...
Fastapi教程:使用 aioredis 连接池执行Redis 的高效异步操作
在构建高性能的 Web 应用时,缓存系统是一个至关重要的组成部分。Redis 是最常见的缓存系统之一,它提供了高效的存储与读取机制。然而,在与 Redis 进行频繁交互时,创建和销毁连接可能会成为瓶颈。为了优化这一问题,我们…...

配置mysqld(读取选项内容,基本配置),数据目录(配置的必要性,目录下的内容,具体文件介绍,修改配置)
目录 配置mysqld 读取选项内容 介绍 启动脚本 基本配置 内容 端口号 数据目录的路径 配置的必要性 配置路径 mysql数据目录 具体文件 修改配置时 权限问题 配置mysqld 读取选项内容 介绍 会从[mysqld] / [server] 节点中读取选项内容 优先读取[server] 虽然服务…...

docker 容器相互访问
目前采用 network 方式 1. 创建自定义网络 docker network create network-group 如下 2. 相互访问的容器更改(目前演示redis 以及netcore api 访问redis ) //redis 原有容器删除 跟之前区别就是加入 --network network-group docker run \ -p 6379:…...

算法1(蓝桥杯18)-删除链表的倒数第 N 个节点
问题: 给你一个链表,删除链表的倒数第 n 个节点,并且返回链表的头节点。 输入:head 1 -> 2 -> 3 -> 4 -> 5 -> null, n 2 输出:1 -> 2 -> 3 -> 5 -> null输入:head 1 ->…...
【PyTorch】动态调整学习率 torch.optim.lr_scheduler.StepLR 调度器
文章目录 1. torch.optim.lr_scheduler.StepLR 官方文档详解2. 使用示例2.1 官方提供使用示例2.2 自己写代码测试方法2.2.1 get_last_lr() 方法2.2.2 state_dict() 方法2.2.3 load_state_dict() 保存和加载调度器 3. 思考3.1 为什么需要state_dict()3.2 get_lr() 与 get_last_l…...
AIGC drug design 人工智能生成式药物设计:基于 GPT 的 SMILES 生成与应用
人工智能生成式药物设计:基于 GPT 的 SMILES 生成与应用 1. 人工智能生成模型:解密 GPT 的工作原理 目录 引言 1.1 背景介绍 1.2 人工智能生成模型的兴起 1.3 GPT 系列模型的地位与影响 GPT 模型概述 2.1 什么是 GPT 2.2 GPT 的发展历程 2.3 GPT 与其…...
Python面试常见问题及答案4
一、内存管理相关 问题:Python中的垃圾回收机制是如何工作的? 答案:Python主要使用引用计数来进行垃圾回收,当对象的引用计数为0时,该对象就会被垃圾回收器回收。此外,Python还有一个循环垃圾收集器来处理循…...

开启第二阶段---蓝桥杯
一、12.10--数据类型的范围及转化 今天是刚开始,一天一道题 对于这道题我想要记录的是Java中的整数默认是 int 类型,如果数值超出了 int 的范围,就会发生溢出错误。为了避免这个问题,可以将数字表示为 long 类型,方法…...

npm内存溢出
项目过大运行项目内存溢出 报错代码 运行内存溢出 increase-memory-limit ‘“node --max-old-space-size8192”’ 不是内部或外部命令,也不是可运行的程序 FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed - JavaScript heap out of m…...

回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测
回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测 目录 回归预测 | MATLAB实现CNN-BiGRU卷积神经网络结合双向门控循环单元多输入单输出回归预测预测效果基本介绍程序设计参考资料预测效果 基本介绍 CNN-BiGRU,即卷积神经网络(CNN)与双…...
Android系统卡启动问题排查
Android系统启动正常来说会涉及到如下几个过程: 引导加载程序(Bootloader)Linux内核(Kernel),负责硬件抽象、内存管理、进程管理、网络堆栈等init进程 init进程读取init.rc配置文件,用于启动各…...

Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...
可靠性+灵活性:电力载波技术在楼宇自控中的核心价值
可靠性灵活性:电力载波技术在楼宇自控中的核心价值 在智能楼宇的自动化控制中,电力载波技术(PLC)凭借其独特的优势,正成为构建高效、稳定、灵活系统的核心解决方案。它利用现有电力线路传输数据,无需额外布…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

HTML 列表、表格、表单
1 列表标签 作用:布局内容排列整齐的区域 列表分类:无序列表、有序列表、定义列表。 例如: 1.1 无序列表 标签:ul 嵌套 li,ul是无序列表,li是列表条目。 注意事项: ul 标签里面只能包裹 li…...
镜像里切换为普通用户
如果你登录远程虚拟机默认就是 root 用户,但你不希望用 root 权限运行 ns-3(这是对的,ns3 工具会拒绝 root),你可以按以下方法创建一个 非 root 用户账号 并切换到它运行 ns-3。 一次性解决方案:创建非 roo…...

BCS 2025|百度副总裁陈洋:智能体在安全领域的应用实践
6月5日,2025全球数字经济大会数字安全主论坛暨北京网络安全大会在国家会议中心隆重开幕。百度副总裁陈洋受邀出席,并作《智能体在安全领域的应用实践》主题演讲,分享了在智能体在安全领域的突破性实践。他指出,百度通过将安全能力…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...

免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...