我试图解决Box<SomeTrait>的序列化和反序列化问题.我知道,在封闭类型层次 struct 的情况下,推荐的方法是使用枚举,它们的序列化没有问题,但在我的情况下,使用枚举是不合适的解决方案.

起初,我try 使用Serde,因为它实际上是一种 rust 迹序列化机制.Serde能够序列化Box<X>,但在X是一个特征的情况下不能.无法为trait对象实现Serialize trait,因为它有泛型方法.这个特殊的问题可以通过使用erased-serde来解决,这样Box<SomeTrait>的序列化就可以工作了.

主要问题是反序列化.要反序列化多态类型,需要在序列化数据中有一些类型标记.这个标记应该首先反序列化,然后用于动态获取返回Box<SomeTrait>的函数.

std::any::TypeId可以用作标记类型,但主要问题是如何动态获取反序列化函数.我不考虑在应用程序初始化期间手动调用每个多态类型的函数的选项.

我知道两种可能的方法:

  1. 具有运行时反射(如C#)的语言可以使用它来获取
  2. 在C++中,谷类库使用静态对象的魔法在库初始化时间中在静态映射中登记反序列化器.

但这两种 Select 在美国都不可用.如果可以的话,如何在Rust中添加多态对象的反序列化?

推荐答案

这已经是implemented by dtolnay了.

这一概念相当聪明,在README篇文章中有解释:

How does it work?

我们使用inventory crate 生成您的特征的impl注册表,它构建在ctor crate 上,用于连接插入注册表的初始化函数.第一个Box<dyn Trait>反序列化将执行迭代注册表和构建标记到反序列化函数的映射的工作.随后的反序列化在该映射中找到正确的反序列化函数.erased-serde crate 也参与其中,以不 destruct 物体安全的方式完成这一切.

总之,声明为[de]可序列化的trait的每个实现都在编译时注册,在trait对象[de]序列化的情况下,这在运行时得到解决.

Rust相关问答推荐

我如何在Rust中使用传递依赖中的特征?

为什么`Vec i64`的和不知道是`Option i64`?

关于使用平面图功能的borrow 判断器的问题

Rust移动/复制涉及实际复制时进行检测

你能在Rust中弃用一个属性吗?

链表堆栈溢出

要求类型参数有特定的大小?

我们可以在 Rust 切片中使用步骤吗?

将泛型中的 Box 转换为 rust 中的 Box

在发布中包含 Rust DLL

max(ctz(x), ctz(y)) 有更快的算法吗?

如何展平以下嵌套的 if let 和 if 语句?

在 Rust 中,将可变引用传递给函数的机制是什么?

为什么在 macOS / iOS 上切换 WiFi 网络时 reqwest 响应会挂起?

为什么基于 clap::Parser 读取的大量数字进行计算比硬编码该数字时慢?

如何用另一个变量向量置换 rust simd 向量?

为什么当borrow 变量发生变化时,borrow 变量不会改变?

在 macro_rules 中转义 $ 美元符号

如果参数为 Send,则返回 Future Send

如何关闭用winit启动的窗口,而不退出程序/进程?