Bssom.Net拥有读取字段而不用完全反序列化和更改值而不用完全序列化功能, 这是因为Bssom协议有着良好的结构化特征, 在Bssom.Net的实现里, 这样的功能则暴露在BssomFieldMarshaller中.
BssomFieldMarshallerBssomFieldMarshaller提供一套API用于对被序列化后的数据进行更低粒度的控制.
API 描述IndexOf 通过特殊的输入格式来获取被指定的对象在Bssom二进制中的位置,返回偏移量信息
ReadValue 通过指定的偏移量信息来读取整个元素
ReadValueType 通过指定的偏移量信息仅读取元素类型
ReadValueTypeCode 通过指定的偏移量信息仅读取元素类型的二进制码
ReadValueSize 通过指定的偏移量信息来获取元素在Bssom二进制中所存储的大小
ReadArrayCountByMapType 通过指定的偏移量信息来读取BssomArray的元素数量
ReadAllKeysByMapType 通过指定的偏移量信息来读取BssomMap中的元数据(包含Key和值的偏移量)
TryWrite 通过指定的偏移量信息在Bssom二进制中重新对值进行写入, 若写入值的宽度大于被写入槽的宽度,则失败
每种方法都提供了 byte[] 和 IBssomBuf 的重载
简单字段访问语言Bssom.Net为IndexOf定义了一种简单的字段访问语言, 该语言共定义了两种访问形式, 一种是访问Map类型(该Map类型的键必须为String类型), 一种是访问Array类型. 两种访问形式可以自由组合.
[Key] : 代表通过Key来访问Map类型的值, 输入的Key只表示String类型
$Index : 代表通过下标来访问Array类型的元素, 输入的Index只能是整数类型
假设有如下数据
{ "Postcodes" : { "WuHan" : [430070,430071,430072,430073], "XiangYang" : [441000,441001,441002] }, "Province" : "HuBei" }可以通过如下方式进行元素访问, 在中可以了解更多细节
[Postcodes][WuHan]$1 => 4330071 [Province] => "HuBei" 自定义字段访问形式接口Bssom.Net为IndexOf提供了IIndexOfInputSource接口用来接收自定义的字段访问源, 使用该接口后Map类型的Key将不再受限制, Key可以为任意输入类型.
IndexOfObjectsInputSource 是 Bssom.Net为用户提供的IIndexOfInputSource接口的通用实现. 它接收一组可迭代的对象,当调用IndexOf的时候, 将依次对对象进行迭代.
假设有如下数据
{ 2018-01-01 : { 0 : ["Rain1","Rain2","Rain3"], 4 : ["Rain4","Fair5","Fair6"] } }可以通过如下方式进行元素访问, 在中可以了解更多细节
new IndexOfObjectsInputSource(new Entry[]{ new Entry(DateTime.Parse("2018-01-01"),ValueIsMapKey: true), new Entry(3,ValueIsMapKey: true), new Entry(1,ValueIsMapKey: false), }) output => "Fair5" 8.动态代码生成Bssom.Net对IDictionaryResolver, ICollectionResolver, MapCodeGenResolver, ObjectResolver 使用了动态代码生成技术, 通过表达式树和Emit共同生成运行时代码, 如果应用程序是纯AOT环境, 则将不支持.
在MapCodeGenResolver中对Map1类型的反序列化使用了以8字节(64位字长)为单位的类前缀树的自动机查找模式, 这是非常有效且快速的方式, 它避免了对字符串进行完全Hash运算以及字符比较开销, 通过对MapCodeGenResolver.Save()方法你将看到这些自动生成的代码.
MapCodeGenResolver中对Map2类型的反序列化则使用了内置的Bssom协议的Map格式查找代码,该代码是状态机模式编写, 分为快速和低速版, 这取决于是否能够提供 .