我希望有人可以说明Microsoft Bond运行时架构(SchemaDef)的常见用例。我理解这些是在编译时不知道模式定义时使用的,但是如果对象的形状是流动的并经常更改,那么运行时生成的模式可能带来哪些好处?
我的用例是业务用户控制对象的形状(通过规则引擎)。他们可以想象做各种可能破坏我们向后兼容性的事情(例如,反转对象上的字段顺序)。如果我们计划持久保存用户创建的所有对象版本,有没有办法使用Bond运行时模式管理向后/向前兼容性?我认为不,好像他们反过来了:
0: int64 myInt;
1: string myString;
到这个
0: string myString;
1: int64 myInt;
我期待运行时错误。这意味着使用运行时模式管理对象不会给我带来太多帮助。
运行时架构实际上有用的用例是什么?
谢谢!
答案 0 :(得分:0)
运行时模式的一些用途是:
如果您可以主动拒绝不兼容的架构,那么您的案例就像架构验证一样。我在一个使用邦德的系统上工作并采用了这种方法。有一个明确的"改变了这个实体的模式"验证两个模式是否相互兼容的操作。
我不知道您系统中的数据流,因此可能无法进行此类验证。在这种情况下,您可以使用运行时模式以及业务用户提供的一些规则来转换不同的形状。
从简单二进制文件反序列化时,读者必须知道编写器使用的确切模式,否则它无法解释字节,从而导致潜在的静默数据损坏。
如果架构经历以下更改,则可能发生此类损坏:
// 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的运行时架构,读者将知道第二个和第三个字节对应于已被删除的字段,并且可以跳过它们,产生预期的Foo { f1:1, f3: 0, f4: 0 }
。
使用Bond的某些系统对于正常的Bond规则的模式演变有不同的规则。运行时模式可用于强制执行此类规则(例如,检查类型以强制执行不使用集合的规则),然后再接受给定类型的结构,或者在已知模式的存储库中注册此类模式之前。
你也可以走两个模式来确定它们是否相互兼容。如果Bond本身提供了这样的API,那将是很好的,因此它不必一次又一次地重新实现。我打开了GitHub issue for such an API。
使用运行时架构,您可以获得有关结构的额外信息,包括字段名称等内容。 (二进制编码协议省略了字段名称,而是依赖于字段ID。)您可以使用此附加信息来执行创建特定于每个字段的GUI控件等操作。
在C ++中,MapTo
转换可用于将一个结构转换为另一个结构,这些结构在给定一组规则的情况下形状不兼容。那里有an example of this,它利用运行时模式来推导规则。