原文地址:https://microsoft.github.io/bond/manual/bond_cs.html

关于

Bond是用于处理程式化数据的一种可扩展框架。适用于从业务通信到大数据存储、处理等各种场景。

Bond定义了类型系统和模式演变规则同时也允许向前或者向后兼容。Bond的核心特性包括了高性能序列化/反序列化以及非常强大的通用数据转换机制。此框架通过可插拔序列化协议、数据流、用户定义的类型别名等具备了很高的扩展性。

根据设计,Bond是独立于语言和平台的,目前支持Linux,macos和Windows上的C++,C#,Java,Python。

Bond仓库发布在Github上: https://github.com/microsoft/bond/

基本示例

在Bond中,数据架构是使用类似 idl 的语法定义的:

  • 在项目文件下引用【Bond.CSharp】Nuget 包
  • 在项目文件下创建xxx.bond文件
  • 在 Nuget 控制台下面输入 gbc C# xxx.bond (gbc 系统在 macos 中要单独装) ```csharp namespace Examples

struct Record { 0: string Name; 1: vector Constants; }

  1. 为了在 C# 程序中使用架构,需要使用 Bond 编译器对其进行编译。此步骤有时也称为代码生成(或代码生成),因为编译会生成与架构定义对应的 C# 代码。<br />在C#程序中需要在Nuget中引入【Bond.CSharp】包。在.NET6中如果编译 bond 文件出现问题(example.bond(1,1) : error B0000: example.bond:1:1:, |, 1 | using System;, | ^^^^^^^^^, unexpected "using Sys", expecting import statement or namespace declaration),不防将全局隐式引用disable掉 <ImplicitUsings>Disable</ImplictiUsings>。
  2. ```csharp
  3. gbc c# example.bond

使用生成的 C# 代码,我们可以编写一个简单的程序,该程序将使用紧凑型二进制协议序列化和反序列化 Record实例:

namespace Examples
{
    using Bond;
    using Bond.Protocols;
    using Bond.IO.Safe;

    class Program
    {
        static void Main()
        {
            var src = new Record
            {
                Name = "FooBar",
                Constants = { 3.14, 6.28 }
            };

            // 将对象src序列化到output缓存中
            var output = new OutputBuffer();
            var writer = new CompactBinaryWriter<OutputBuffer>(output);

            // The first calls to Serialize.To and Deserialize<T>.From can take
            // a relatively long time because they generate the de/serializer
            // for a given type and protocol.
            Serialize.To(writer, src);

            // 反序列化到input缓存中
            var input = new InputBuffer(output.Data);
            var reader = new CompactBinaryReader<InputBuffer>(input);

            var dst = Deserialize<Record>.From(reader);
            Console.WriteLine(dst.Name);
            Console.WriteLine(dst.Constants[0]);
            Console.ReadLine();
        }
    }
}

代码生成

为了在C#程序中使用Bond架构,需要使用Bond编译器gbc对Bond文件进行编译。编译器会根据Bond文件生成同等效果的C#类。默认情况下,字段由默认构造函数中的可访问的自动初始化属性表示。(这边用人话说其实是Bond中定义的字段会被转换为C#类中的属性)

Bond和C#类型系统之间的映射关系非常明显, 但值得注意的是, 与C#引用类型不同, Bond类型不可空。 这就意味着Bond中的字符串被映射到C#中是引用类型(不可空)。为了允许空值,必须将类型声明为可空,例如:

struct Foo
{
    0: list<nullable<string>> listOfNullableStrings;
}

在Bond IdL中声明的字段,值null也是合法的,其默认值为nothing,例如:

struct Bar
{
    0: string str = nothing;
}

可以通过将以下一个或多个命令行选项传递给gbc来自定义生成代码:
—fields:架构字段将被转换为带有初始值的公开字段,并且不会生成构造函数。
—readonly-properties:架构字段将被转换为public get private set属性,并用默认值初始化属性在默认构造函数中。具有只读属性的类完全受所有Bond APIs支持。
—preview-constructor-parameters:将生成一个带有参数的构造函数,用于初始化每个架构字段。此选项通常与 —只读属性结合使用。此功能处于预览状态,可能会更改。
—collection-interfaces:集合类型 vector, map, list 和 set 将被转换为泛型集合接口类型:IList, IDictionary, ICollection and ISet

序列化

Bond序列化 API 由Serializer 类提供。它是一个泛型类,被用于序列化的写入协议类型来进行参数化:

Serializer<CompactBinaryWriter<OutputStream>>

Serializer 类的构造函数用Bond转换后的类型传入进去:

new Serializer<CompactBinaryWriter<OutputStream>>(typeof(Record))

构造函数是非常重要的,故应用程序通常在内部循环之外创建序列化程序的实例并重用它。(对Serializer实例对象重用)
Serializer类公开了一个方法,该方法有两个参数,一个是即将被序列化的对象和一个用于序列化的协议编写器实例。serializer.Serialize(obj, writer);
对象的类型必须与传递给序列化程序构造函数的类型相同,否则会报undefined错误。
Bond 为使用编译时已知的架构类型且不需要管理序列化程序生存期的应用程序提供了一个帮助静态API:

Serialize.To(writer, obj);

当第一次调用API的时候,会创建相应的静态实例。由于第一次给给定类型和协议调用API可能需要较长时间。对相同的 writer/object 类型的后续调用会重用静态实例。

反序列化

Bond 反序列化 API 由 Deserializer 类提供。它是一种泛型类,参数为用于反序列化协议读取类型。