我試圖解決序列化和反序列化的問題Box<SomeTrait>
。我知道,在封閉類型層次結構的情況下,推薦的方法是使用枚舉,並且序列化沒有問題,但在我的情況下使用枚舉是不合適的解決方案。如何在Rust中添加多態性特徵對象的反序列化?
起初我試圖使用Serde,因爲它是事實上的Rust序列化機制。 Serde能夠序列化Box<X>
,但不是在X
是特徵的情況下。 Serialize
特徵不能用於特徵對象,因爲它具有通用方法。這個特殊問題可以通過使用erased-serde來解決,因此Box<SomeTrait>
的序列化可以工作。
主要問題是反序列化。要反序列化多態類型,你需要在序列化數據中有一些類型標記。這個標記應首先反序列化,然後用於動態獲取將返回Box<SomeTrait>
的函數。
std::any::TypeId
可以用作標記類型,但主要問題是如何動態獲取反序列化函數。我不考慮爲應用程序初始化期間應手動調用的每種多態類型註冊一個函數的選項。
我知道兩種可能的方式做到這一點:
- 有像C#運行時反射可以用它來獲得 反序列化方法的語言。
- 在C++中,穀物庫使用靜態對象的魔術來在庫初始化時在靜態映射中註冊反序列化器。
但是這些選項在Rust中都沒有。如何在Rust中添加多態對象的反序列化?
「但在我的情況下使用枚舉是不合適的解決方案。」我們能知道爲什麼嗎?這聽起來像整個問題會在使用枚舉時消失。請注意,'erased_serde'中的類型擦除發生在'Deserializer'處,而不是被反序列化的對象。 –
「我們可以知道爲什麼嗎?」我試圖讓最少的依賴關係。我在一些非常小的非常基本的模塊中有一個特性,並且有很多代碼依賴於它。我希望將這個特徵的每個實現都放在一個單獨的模塊中。另外還有使用 –
的另一個缺點對不起,我在意外完成前意外發表了評論。此外還有使用枚舉的另一個缺點:如果在所有枚舉子類型中使用相同的方法在枚舉上調用它,則必須爲每種類型添加類似案例的「匹配」構造。 「erased_serde中的類型擦除發生在反序列化器中,而不是反序列化的對象上」是的,我知道這一點。我在問題中提到,erased_serder不能解決反序列化問題,只能用序列化。 –