运行时模式的一些用途是:
- 使用简单二进制协议来处理架构更改
- 模式验证/进化
- 在 GUI 中呈现结构
- 从一个结构到另一个结构的自定义映射
如果您可以主动拒绝不兼容的架构,您的案例感觉就像架构验证。我开发了一个在底层使用 Bond 的系统,并采用了这种方法。有一个明确的“更改此实体的架构”操作来验证这两个架构是否相互兼容。
我不知道您系统中的数据流,因此可能无法进行此类验证。在这种情况下,您可以使用运行时模式以及业务用户提供的一些规则来在不同形状之间进行转换。
简单二进制
从 Simple Binary 反序列化时,读者必须知道作者使用的确切模式,否则无法解释字节,从而导致潜在的静默数据损坏。
如果架构发生以下更改,则可能发生此类损坏:
// 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 那就太好了,这样就不必一次又一次地重新实现它。我已经为这样的 API 打开了一个 GitHub 问题。
图形用户界面
使用运行时模式,您可以获得有关结构的额外信息,包括字段名称等信息。(二进制编码协议省略了字段名称,而是依赖于字段 ID。)您可以使用这些附加信息来执行诸如创建特定于每个字段的 GUI 控件之类的事情。
有一个示例显示了在C#和C++中检查运行时模式。
自定义映射
在 C++ 中,在MapTo
给定一组规则的情况下,转换可用于将一个结构转换为另一个不兼容的形状。有一个这样的例子,它使用运行时模式来派生规则。