serialization - 如何抽象化Rust中可远程或本地化的可序列化对象?

标签 serialization rust enums rpc abstraction

我有一个枚举来表示节点是本地节点(指当前节点)还是远程节点,在这种情况下,通信是通过RPC调用进行的:

pub enum Node {
    Local,
    Remote(SocketAddr),
}
我有一个代表本地数据库的DB结构。我需要序列化此Node枚举,因为它用作元数据来确定某些键值对的存储位置(本地或远程)。我将此元数据与其余数据存储在同一数据库中,因此Node::Local指的是它存储在其中的数据库。
我希望反序列化的节点枚举包含对该数据库的引用,以便可以将该Local变体转换为Local(DB)。然后,对于LocalRemote变体,我将具有相同的语义,因为它们都包含足够的信息来执行Node.get(key)Node.insert(key, value)操作。
对于远程变体,我只需要打开到SocketAddr的连接并发出RPC请求,但是对于Local变体,我必须在我对本地数据库有引用的地方进行模式匹配,并应用特殊的逻辑而不是通常可以说Node.get(key)。基本问题是Node::Local包含的信息不足,无法对本地数据库执行请求,而SocketAddr中的Node::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都实现相同的特征。
特征特别有用,因为它允许添加新的节点类型(本地和远程),而无需更改任何旧代码。使用枚举时,预期只有两种不同的枚举情况的代码将在添加新的节点类型时中断。通过应用经典的OOP模式(如访客模式),也可以克服特征对象的局限性。

关于serialization - 如何抽象化Rust中可远程或本地化的可序列化对象?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64847691/

相关文章:

php - 如何获得序列化输出数据?

vba - 如何将树结构写入磁盘(没有序列化的 VBA)

rust - 是否有任何编译器标志来强制有符号整数溢出的未定义行为?

c++ - 将位掩码整数和枚举存储在相同的值中。如何?

php - 如何验证 laravel 中插入的图像数组并需要根据验证插入枚举值?

c# - IgnoreDataMember 不起作用,但 JsonIgnore 起作用

jquery - 有没有办法使用 jQuery 的序列化表单字段并修剪字段中的值?

rust - 借用检查器 : Cannot borrow as immutable because it is also borrowed as mutable

arrays - 如何打印数组和向量?

python - 为什么在将字符串字段添加到由 Enum 实例化的数据类时会出现 AttributeError?