Microsoft Bond 运行时 schemaDef

Microsoft Bond runtime schemaDef

我希望有人可以说明 Microsoft Bond 运行时模式 (SchemaDef) 的常见用例。我知道这些在编译时模式定义未知时使用,但如果对象的形状是流动的并且经常变化,运行时生成的模式可能提供什么好处?

我的用例是业务用户控制对象的形状(通过规则引擎)。可以想象,它们可以做各种可能破坏我们的向后兼容性的事情(例如,反转对象上字段的顺序)。如果我们计划保留用户创建的所有对象版本,是否有任何方法可以使用 Bond 运行时模式来管理 backward/forward 兼容性?我想不,好像他们从这个反转:

0: int64 myInt;
1: string myString;

到这个

0: string myString;
1: int64 myInt;

我预计会出现运行时错误。这意味着使用运行时模式管理对象不会为我提供太多帮助。

运行时模式实际上有用的用例是什么?

谢谢!

运行时模式的一些用途是:

  • 使用简单二进制协议来处理架构更改
  • 架构validation/evoluton
  • 在 GUI 中呈现结构
  • 从一个结构到另一个结构的自定义映射

如果您可以 pro-actively 拒绝不兼容的模式,您的情况就像模式验证。我开发了一个在后台使用 Bond 的系统,并采用了这种方法。有一个显式的“更改此实体的架构”操作验证了这两个架构是否相互兼容。

我不知道您系统中的数据流,因此可能无法进行此类验证。在这种情况下,您可以使用运行时模式以及业务用户提供的一些规则在不同形状之间进行转换。

简单二进制

从简单二进制反序列化时,reader 必须知道 作者使用的确切模式,否则它无法解释字节,从而可能导致静默数据损坏。

如果模式发生以下变化,就会发生这种损坏:

// starting struct
struct Foo
{
    0: uint8 f1;
    1: uint16 f2;
}

Foo { f1: 1, f2: 2} 的简单二进制序列化表示是 0x01 0x02 0x00

现在让我们将架构更改为:

// changed struct
struct Foo
{
    0: uint8 f1;
    // It's OK to remove an optional field.
    // 1: uint16 f2;
    2: uint8 f3;
    3: uint8 f4;
}

如果我们使用此模式反序列化 0x01 0x02 0x00,我们将得到 Foo { f1: 1, f3: 2, f4: 0}。请注意 f3 是 2,这是不正确的:它应该是 0。使用旧 Foo 的运行时模式,reader 将知道第二个和第三个字节对应于自已被删除并可以跳过它们,从而产生预期的 Foo { f1:1, f3: 0, f4: 0 }.

模式验证和演变

一些使用 Bond 的系统具有与普通 Bond 规则不同的模式演化规则。运行时模式可用于在接受给定类型的结构之前或在例如已知模式的存储库中注册此类模式之前强制执行此类规则(例如,检查类型以强制执行不使用集合的规则)。

您还可以遍历两个模式以确定它们是否相互兼容。如果 Bond 自己提供这样的 API 就好了,这样它就不必一次又一次地重新实现。我打开了 GitHub issue for such an API.

图形界面

使用运行时架构,您可以获得有关结构的额外信息,包括字段名称等信息。 (二进制编码协议省略字段名称,取而代之的是字段 ID。)您可以使用此附加信息来执行诸如创建特定于每个字段的 GUI 控件之类的操作。

有一个示例显示在 C# and C++.

中检查运行时模式

自定义映射

在 C++ 中,MapTo transform can be used to convert one struct to another, which incompatible shapes, given a set of rules. There's an example of this 使用运行时模式来派生规则。