【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配置文件,用于启动各…...
C++初阶-list的底层
目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
day52 ResNet18 CBAM
在深度学习的旅程中,我们不断探索如何提升模型的性能。今天,我将分享我在 ResNet18 模型中插入 CBAM(Convolutional Block Attention Module)模块,并采用分阶段微调策略的实践过程。通过这个过程,我不仅提升…...
循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
【项目实战】通过多模态+LangGraph实现PPT生成助手
PPT自动生成系统 基于LangGraph的PPT自动生成系统,可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析:自动解析Markdown文档结构PPT模板分析:分析PPT模板的布局和风格智能布局决策:匹配内容与合适的PPT布局自动…...
uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
HTML前端开发:JavaScript 常用事件详解
作为前端开发的核心,JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例: 1. onclick - 点击事件 当元素被单击时触发(左键点击) button.onclick function() {alert("按钮被点击了!&…...
前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
