IBufferWriter<T>是同步缓冲写入的协定,实现这个接口就拥有一个输出接收器
我是最近研究Protobuf序列化时发现它有个传递IBufferWriter<T>的构造,使用者只需要自己实现一个IBufferWriter<T>,创建后传递给Protobuf-net的序列化函数,就能得到其序列化后的字节流
先实现一个IBufferWriter<T>
/// <summary> /// 实现IBufferWriter<T>接口的写入器 /// </summary> public class BufferWriter : IBufferWriter<byte> { /// <summary> /// 缓冲区 /// </summary> byte[] buffer; /// <summary> /// 缓冲区中数据的个数 /// </summary> int length; /// <summary> /// 初始容量 /// </summary> readonly int capacity; /// <summary> /// 创建一个缓冲区写入器 /// </summary> /// <param name="capacity"></param> public BufferWriter(int capacity) { this.capacity = capacity; buffer = new byte[capacity]; } /// <summary> /// 重置长度,复用该对象 /// </summary> public void Reset() { length = 0; } /// <summary> /// 得到缓冲区中的数据 /// </summary> /// <returns></returns> public (byte[], int) GetBuffer() { return (buffer, length); } /// <summary> /// 实现接口, /// </summary> /// <param name="count"></param> public void Advance(int count) { length += count; } /// <summary> /// 当缓冲区长度不足时,扩容缓冲区 /// </summary> /// <param name="sizeHint"></param> void TryExpand(int sizeHint) { if (sizeHint + length > buffer.Length) { Array.Resize(ref buffer, buffer.Length + capacity); } } /// <summary> /// 返回缓冲区指定长度的可操作块 /// </summary> /// <param name="sizeHint"></param> /// <returns></returns> public Memory<byte> GetMemory(int sizeHint = 0) { TryExpand(sizeHint); return buffer.AsMemory(length, sizeHint); } /// <summary> /// 返回缓冲区指定长度的可操作块 /// </summary> /// <param name="sizeHint"></param> /// <returns></returns> public Span<byte> GetSpan(int sizeHint = 0) { TryExpand(sizeHint); return buffer.AsSpan(length, sizeHint); } }View Code
写了一段测试代码来理解它
public async Task Test() { await Task.CompletedTask; BufferWriter bw = new BufferWriter(1024); //这是一个缓冲区写入器 for (int i = 0; i < 3; i++) { //循环测试其复用性 bw.Reset(); //重置缓冲区复用创建的写入器对象 TestWrite(bw); (byte[] buffer, int length) = bw.GetBuffer(); //得到缓冲区数据 Console.WriteLine($"{string.Join(",", buffer.Take(length))}"); //输出写入的数据 } } /// <summary> /// 模拟向缓冲区中写数据 /// </summary> void TestWrite(BufferWriter bw) { byte[] bytes = BitConverter.GetBytes(1024); //第一条数据,int32 //使用接口中方法写入数据 Span<byte> span = bw.GetSpan(bytes.Length); //先从申请一个span bytes.CopyTo(span); //然后将数据写入其中 bw.Advance(bytes.Length); //通知写入器已写入数据的长度 //使用IBufferWriter<T>的扩展方法能直接写入数据 bw.Write(BitConverter.GetBytes(4096)); //第二条数据 } }
标签:C#,写入,接口,int,length,buffer,IBufferWriter,缓冲区 From: https://www.cnblogs.com/luludongxu/p/17957066