上街区组织召开工贸企业主要负责人安全生产工作座谈会
为深入开展重大事故隐患专项排查整治行动和安全生产异地交叉检查工作,
上文说到Unmanaged、BufferedBinary和BufferedString是NativeBuffering支持的三个基本数据类型,其实我们也可以说NativeBuffering只支持Unmanaged和IReadOnlyBufferedObject
一、IReadOnlyBufferedObject一、IReadOnlyBufferedObject
二、集合三、字典四、为什么不直接返回接口?
顾名思义,IReadOnlyBufferedObject
(资料图片)
public interface IReadOnlyBufferedObjectwhere T: IReadOnlyBufferedObject { static abstract T Parse(NativeBuffer buffer);}public unsafe readonly struct NativeBuffer{ public byte[] Bytes { get; } public void* Start { get; } public NativeBuffer(byte[] bytes, void* start) { Bytes = bytes ?? throw new ArgumentNullException(nameof(bytes)); Start = start; } public NativeBuffer(byte[] bytes, int index = 0) { Bytes = bytes ?? throw new ArgumentNullException(nameof(bytes)); Start = Unsafe.AsPointer(ref bytes[index]); }}
由于IReadOnlyBufferedObject
[BufferedMessageSource]public partial class Contact{ public Contact(string id, string name, Address address) { Id = id; Name = name; ShipAddress = address; } public string Id { get; } public string Name { get; } public Address ShipAddress { get; }}[BufferedMessageSource]public partial class Address{ public string Province { get; } public string City { get; } public string District { get; } public string Street { get; } public Address(string province, string city, string district, string street) { Province = province ?? throw new ArgumentNullException(nameof(province)); City = city ?? throw new ArgumentNullException(nameof(city)); District = district ?? throw new ArgumentNullException(nameof(district)); Street = street ?? throw new ArgumentNullException(nameof(street)); }}
Contact具有Id、Name和ShipAddress 三个数据成员,ShipAddress 对应的Address又是一个复合类型,具有四个表示省、市、区和介绍的字符串类型成员。现在我们为Contact和Address这两个类型生成对应的ContactBufferedMessage和AddressBufferedMessage。
public unsafe readonly struct ContactBufferedMessage : IReadOnlyBufferedObject{ public NativeBuffer Buffer { get; } public ContactBufferedMessage(NativeBuffer buffer) => Buffer = buffer; public static ContactBufferedMessage Parse(NativeBuffer buffer) => new ContactBufferedMessage(buffer); public BufferedString Id => Buffer.ReadBufferedObjectField (0); public BufferedString Name => Buffer.ReadBufferedObjectField (1); public AddressBufferedMessage ShipAddress => Buffer.ReadBufferedObjectField (2);}public unsafe readonly struct AddressBufferedMessage : IReadOnlyBufferedObject { public NativeBuffer Buffer { get; } public AddressBufferedMessage(NativeBuffer buffer) => Buffer = buffer; public static AddressBufferedMessage Parse(NativeBuffer buffer) => new AddressBufferedMessage(buffer); public BufferedString Province => Buffer.ReadBufferedObjectField (0); public BufferedString City => Buffer.ReadBufferedObjectField (1); public BufferedString District => Buffer.ReadBufferedObjectField (2); public BufferedString Street => Buffer.ReadBufferedObjectField (3);}
如下的程序演示了如何将一个Contact对象转换成字节数组,然后利用这这段字节序列生成一个ContactBufferedMessage对象。给出的调试断言验证了Contact和ContactBufferedMessage对象承载了一样的数据,fixed关键字是为了将字节数组“固定住”。(源代码从这里下载)
using NativeBuffering;using System.Diagnostics;var address = new Address("Jiangsu", "Suzhou", "Industory Park", "#328, Xinghu St");var contact = new Contact("123456789", "John Doe", address);var size = contact.CalculateSize();var bytes = new byte[size];var context = new BufferedObjectWriteContext(bytes);contact.Write(context);unsafe{ fixed (byte* _ = bytes) { var contactMessage = ContactBufferedMessage.Parse(new NativeBuffer(bytes)); Debug.Assert(contactMessage.Id == "123456789"); Debug.Assert(contactMessage.Name == "John Doe"); Debug.Assert(contactMessage.ShipAddress.Province == "Jiangsu"); Debug.Assert(contactMessage.ShipAddress.City == "Suzhou"); Debug.Assert(contactMessage.ShipAddress.District == "Industory Park"); Debug.Assert(contactMessage.ShipAddress.Street == "#328, Xinghu St"); }}二、集合
NativeBuffering同样支持集合。由于Unmanaged和IReadOnlyBufferedObject
以如下所示的Entity为例,它具有两个数组类型的属性成员Collection1和Collection2,数组元素类型分别为Foobar和double,它们分别代表了上述的两种集合类型。
[BufferedMessageSource]public partial class Entity{ public Foobar[] Collection1 { get; } public double[] Collection2 { get; } public Entity(Foobar[] collection1, double[] collection2) { Collection1 = collection1; Collection2 = collection2; }}[BufferedMessageSource]public partial class Foobar{ public int Foo { get; } public string Bar { get; } public Foobar(int foo, string bar) { Foo = foo; Bar = bar; }}
NativeBuffering.Generator会将作为“源类型”的Entity和Foobar类型的生成对应的BufferedMessage类型(EntityBufferredMessage和FoobarBufferedMessage)。从EntityBufferredMessage类型的定义可以看出,两个集合属性的分别是ReadOnlyVariableLengthTypeList
public unsafe readonly struct EntityBufferedMessage : IReadOnlyBufferedObject{ public NativeBuffer Buffer { get; } public EntityBufferedMessage(NativeBuffer buffer) => Buffer = buffer; public static EntityBufferedMessage Parse(NativeBuffer buffer) => new EntityBufferedMessage(buffer); public ReadOnlyVariableLengthTypeList Collection1 => Buffer.ReadBufferedObjectCollectionField (0); public ReadOnlyFixedLengthTypedList Collection2 => Buffer.ReadUnmanagedCollectionField (1);}public unsafe readonly struct FoobarBufferedMessage : IReadOnlyBufferedObject { public NativeBuffer Buffer { get; } public FoobarBufferedMessage(NativeBuffer buffer) => Buffer = buffer; public static FoobarBufferedMessage Parse(NativeBuffer buffer) => new FoobarBufferedMessage(buffer); public System.Int32 Foo => Buffer.ReadUnmanagedField (0); public BufferedString Bar => Buffer.ReadBufferedObjectField (1);}
两个集合类型都实现了IEnumerable
using NativeBuffering;using System.Diagnostics;var entity = new Entity( collection1: new Foobar[] { new Foobar(1, "foo"), new Foobar(2, "bar") }, collection2: new double[] { 1.1, 2.2 });var bytes = new byte[entity.CalculateSize()];var context = new BufferedObjectWriteContext(bytes);entity.Write(context);unsafe{ fixed (byte* p = bytes) { var entityMessage = EntityBufferedMessage.Parse(new NativeBuffer(bytes)); var foobar = entityMessage.Collection1[0]; Debug.Assert(foobar.Foo == 1); Debug.Assert(foobar.Bar == "foo"); foobar = entityMessage.Collection1[1]; Debug.Assert(foobar.Foo == 2); Debug.Assert(foobar.Bar == "bar"); Debug.Assert(entityMessage.Collection2[0] == 1.1); Debug.Assert(entityMessage.Collection2[1] == 2.2); }}三、字典
从数据的存储来看,字典就是键值对的集合,所以我们采用与集合一致的存储形式。NativeBuffering对集合的Key作了限制,要求其类型只能是Unmanaged和字符串(String/BufferredString)。按照Key和Value的类型组合,我们一共定义了四种类型的字典类型,它们分别是:
ReadOnlyUnmanagedUnmanagedDictionary如果Key和Value的类型都是Unmanaged,键值对就是定长类型,所以我们会采用类似于ReadOnlyFixedLengthTypedList
但是这仅仅解决了字段数据存储的问题,字典基于哈希检索定位的功能是没有办法实现的。这里我们不得不作出妥协,四种字典的索引均不能提供时间复杂度O(1)的哈希检索方式。为了在现有的数据结构上使针对Key的查找尽可能高效,在生成字节内容之前,我们会按照Key对键值对进行排序,这样我们至少可以采用二分法的形式进行检索,所以四种类型的字典的索引在根据指定的Key查找对应Value,对应的时间复杂度为Log(N)。如果字典包含的元素比较多,这样的查找方式不能满足我们的需求,我们可以I将它们转换成普通的Dictionary
我们照例编写一个简答的程序来演示针对字典的使用。我们定义了如下这个Entity作为“源类型”,它的四个属性对应的字典类型刚好对应上述四种键值对的组合。从生成的EntityBufferedMessage类型可以看出,四个成员的类型正好对应上述的四种字典类型。
[BufferedMessageSource]public partial class Entity{ public DictionaryDictionary1 { get; set; } public Dictionary Dictionary2 { get; set; } public Dictionary Dictionary3 { get; set; } public Dictionary Dictionary4 { get; set; }}public unsafe readonly struct EntityBufferedMessage : IReadOnlyBufferedObject { public NativeBuffer Buffer { get; } public EntityBufferedMessage(NativeBuffer buffer) => Buffer = buffer; public static EntityBufferedMessage Parse(NativeBuffer buffer) => new EntityBufferedMessage(buffer); public ReadOnlyUnmanagedUnmanagedDictionary Dictionary1 => Buffer.ReadUnmanagedUnmanagedDictionaryField (0); public ReadOnlyUnmanagedBufferedObjectDictionary Dictionary2 => Buffer.ReadUnmanagedBufferedObjectDictionaryField (1); public ReadOnlyStringUnmanagedDictionary Dictionary3 => Buffer.ReadStringUnmanagedDictionaryField (2); public ReadOnlyStringBufferedObjectDictionary Dictionary4 => Buffer.ReadStringBufferedObjectDictionaryField (3);}
如下的代码演示了基于四种字典类型基于“索引”的检索方式(源代码从这里下载)。
using NativeBuffering;using System.Diagnostics;var entity = new Entity{ Dictionary1 = new Dictionary四、为什么不直接返回接口{ { 1, 1 }, { 2, 2 }, { 3, 3 } }, Dictionary2 = new Dictionary { { 1, "foo" }, { 2, "bar" }, { 3, "baz" } }, Dictionary3 = new Dictionary { { "foo", 1 }, { "bar", 2 }, { "baz", 3 } }, Dictionary4 = new Dictionary { { "a", "foo" }, { "b", "bar" }, { "c", "baz" } }};var bytes = new byte[entity.CalculateSize()];var context = new BufferedObjectWriteContext(bytes);entity.Write(context);unsafe{ fixed (void* _ = bytes) { var bufferedMessage = EntityBufferedMessage.Parse(new NativeBuffer(bytes)); ref var value1 = ref bufferedMessage.Dictionary1.AsRef(1); Debug.Assert(value1 == 1); ref var value2 = ref bufferedMessage.Dictionary3.AsRef("baz"); Debug.Assert(value2 == 3); var dictionary1 = bufferedMessage.Dictionary1; Debug.Assert(dictionary1[1] == 1); Debug.Assert(dictionary1[2] == 2); Debug.Assert(dictionary1[3] == 3); var dictionary2 = bufferedMessage.Dictionary2; Debug.Assert(dictionary2[1] == "foo"); Debug.Assert(dictionary2[2] == "bar"); Debug.Assert(dictionary2[3] == "baz"); var dictionary3 = bufferedMessage.Dictionary3; Debug.Assert(dictionary3["foo"] == 1); Debug.Assert(dictionary3["bar"] == 2); Debug.Assert(dictionary3["baz"] == 3); var dictionary4 = bufferedMessage.Dictionary4; Debug.Assert(dictionary4["a"] == "foo"); Debug.Assert(dictionary4["b"] == "bar"); Debug.Assert(dictionary4["c"] == "baz"); }}
针对集合,NativeBuffering提供了两种类型;针对字典,更是定义了四种类型,为什么不直接返回IList
public readonly unsafe struct ReadOnlyFixedLengthTypedList: IReadOnlyList , IReadOnlyBufferedObject > where T: unmanaged{ public readonly ref T AsRef(int index); ...}public unsafe readonly struct ReadOnlyUnmanagedUnmanagedDictionary : IReadOnlyDictionary , IReadOnlyBufferedObject > where TKey : unmanaged, IComparable where TValue : unmanaged{ public readonly ref TValue AsRef(TKey index) ; ...}
关键词:
为深入开展重大事故隐患专项排查整治行动和安全生产异地交叉检查工作,
杭州雷峰塔位于浙江省杭州市西湖区,是中国著名的古建筑之一。雷峰
金坛烟草联合黄金村开展助农直播活动。李星颖摄“山水有相逢,网聚金丝
甲状腺癌的治疗包括手术、激素替代治疗、放射碘治疗及外放射治疗。甲状
1、红色在中国传统文化中代表喜庆和希望,但是红色并不适合作为卧室的
齐襄公死后的王位归属,其实是两个谋臣决定的,鲍叔牙略胜一筹,襄公死
7月31日上午,福州市仓山区委宣传部发布消息称,台屿路一餐厅发生爆炸3
近日,广发银行长沙分行党委书记、行长董朝红率分行党委班子前往山河智
每经AI快讯,有投资者在投资者互动平台提问:有2个问题。请问公司的煤
在今天举行的新闻发布会上,交通运输部综合规划司副司长李传光表示,下
民进党学伦问题频传,继轰动全台的林智坚“学位双杀”之后,又爆出了蒋
前言:ICInsights预测从2021年到2026年,全球MCU市场规模的复合增长率
截至7月30日晚,第31届世界大学生夏季运动会经过前两个比赛日的激战,
导读1、第四忍术要全通关之后,总评分在A或A以上才可以获得2、
中国物流与采购联合会7月28日公布了今年上半年物流运行数据。随着社会
Copyright 2015-2022 华中双创网 版权所有 备案号:京ICP备12018864号-26 联系邮箱:2 913 236 @qq.com
随着全光网络越织越密 如何进一步增强消费者和产业界的“获得感”?
近年来,在5G和宽带双千兆牵引下,新项目、新试点、新应用层出不穷。随着全光网络越织越密,如何进一步增强消费者和产业界的获得感?湖北日
致敬老将!热爱可抵岁月漫长
<script src="http: tv people com cn img player v js">< script><script>showPlayer({id:" pvservice xml 202
微视频|字里藏情迎元宵
<script src="http: tv people com cn img player v js">< script><script>showPlayer({id:" pvservice xml 202