serialization - 如何在 Rust 中抽象出远程或本地的可序列化对象?
问题描述
我有一个枚举来表示节点是本地的(指当前节点)或远程的,在这种情况下,通信是通过 RPC 调用发生的:
pub enum Node {
Local,
Remote(SocketAddr),
}
我有一个DB
代表本地数据库的结构。我需要序列化这个Node
枚举,因为它被用作元数据来确定某些键值对的存储位置(本地或远程)。我将此元数据存储在与其余数据相同的数据库中,因此Node::Local
指的是存储它的数据库。
我希望反序列化的节点枚举包含对它被取出的数据库的引用,以便我可以将该Local
变体转换为Local(DB)
. Local
然后,对于变体,我将拥有相同的语义,Remote
因为它们都包含足够的信息来执行Node.get(key)
和Node.insert(key, value)
操作。
对于远程变体,我只需打开SocketAddr
与Local
笼统地说Node.get(key)
。根本问题是它Node::Local
不包含足够的信息来执行对本地数据库的请求,而SocketAddr
inNode::Remote
足以执行 RPC 调用。
我可以通过创建一个自定义反序列化方法来解决这个问题,在该方法中我将当前DB
作为对该反序列化方法的引用传递,但我想知道是否有其他好的方法来解决这个问题。
解决方案
我最终将这种区别表示为枚举。用单独的枚举进行序列化和实际工作,因为我无法序列化对本地数据库的引用,如果你不需要序列化,你当然可以避开 NodeRepr 枚举:
#[derive(Serialize, Deserialize)]
pub enum NodeRepr {
Local,
Remote(NodeRef),
}
pub enum Node<'a> {
Local(&'a LocalDB),
Remote(NodeRef),
}
然后,节点枚举具有 impl 方法,通过 match 语句将必要的方法调用委托给 localdb 或 NodeRef 方法。
impl Node {
pub async fn get(&self, key: String) -> Option<String> {
match self {
Node::Local(db) => db.get(key),
Node::Remote(noderef) => noderef.get(key).await,
}
}
}
这种处理方式允许我们仍然保留节点是本地还是远程的信息,因此我们可以在必要时在代码中的任何地方使用这些信息。这很有用,因为您通常不希望总是隐藏某物是本地还是远程的信息。
例如,如果您总是想隐藏一个节点是远程还是本地以强制执行代码清洁,您可以使用 trait 对象,您可以让 LocalDB 和 NodeRef 都实现相同的 trait。
特征特别有用,因为它允许添加新的节点类型(本地和远程之外),而无需更改任何旧代码。使用枚举,期望只有两种不同枚举情况的代码将在添加新节点类型时中断。特征对象的限制也可以通过应用经典的 OOP 模式(如访问者模式)来克服。
推荐阅读
- ios - 苹果铅笔点击手势识别问题
- javascript - 从 Javascript 到 Go 的字符串模 Int
- python - pybind11::dict 中的 pybind11::object
- python - 如何找到与拟合双高斯的 y 轴的交点
- google-apps-script - 谷歌电子表格,第一列是脚本选择的
- php - Mysql比较json列和数组
- google-app-engine - App Engine URL Fetch 错误:从服务器收到格式错误的 HTTP 回复
- python - 当我添加更多隐藏层时,神经网络仅产生 1 的值
- java - Jpa 存储库未从数据库中删除
- powershell - 使用 Stream Writer 导出为 CSV