2017-05-28 26 views
10

我试图解决序列化和反序列化的问题Box<SomeTrait>。我知道,在封闭类型层次结构的情况下,推荐的方法是使用枚举,并且序列化没有问题,但在我的情况下使用枚举是不合适的解决方案。如何在Rust中添加多态性特征对象的反序列化?

起初我试图使用Serde,因为它是事实上的Rust序列化机制。 Serde能够序列化Box<X>,但不是在X是特征的情况下。 Serialize特征不能用于特征对象,因为它具有通用方法。这个特殊问题可以通过使用erased-serde来解决,因此Box<SomeTrait>的序列化可以工作。

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

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

我知道两种可能的方式做到这一点:

  1. 有像C#运行时反射可以用它来获得 反序列化方法的语言。
  2. 在C++中,谷物库使用静态对象的魔术来在库初始化时在静态映射中注册反序列化器。

但是这些选项在Rust中都没有。如何在Rust中添加多态对象的反序列化?

+1

“但在我的情况下使用枚举是不合适的解决方案。”我们能知道为什么吗?这听起来像整个问题会在使用枚举时消失。请注意,'erased_serde'中的类型擦除发生在'Deserializer'处,而不是被反序列化的对象。 –

+1

“我们可以知道为什么吗?”我试图让最少的依赖关系。我在一些非常小的非常基本的模块中有一个特性,并且有很多代码依赖于它。我希望将这个特征的每个实现都放在一个单独的模块中。另外还有使用 –

+1

的另一个缺点对不起,我在意外完成前意外发表了评论。此外还有使用枚举的另一个缺点:如果在所有枚举子类型中使用相同的方法在枚举上调用它,则必须为每种类型添加类似案例的“匹配”构造。 “erased_serde中的类型擦除发生在反序列化器中,而不是反序列化的对象上”是的,我知道这一点。我在问题中提到,erased_serder不能解决反序列化问题,只能用序列化。 –

回答

0

您的所有库都可以提供一个注册例程,由std::sync::Once保护,它将一些标识符注册到共同的static mut中,但显然您的程序必须将它们全部称为它们。

我不知道如果TypeId跨不同的依赖关系重新编译产生一致的值。

相关问题