基于键值对形式的二进制数据包生成解析工具, 方便在网络上传输数据.
- 示例代码:
Program.cs
- 单元测试:
Entrance.cs
- NuGet Package:
Mikodev.Exchange
引用命名空间
using Mikodev.Network;
基本格式读写
var packet = new PacketWriter()
.SetValue("id", Guid.NewGuid())
.SetValue("name", "Alice")
.SetItem("data", new PacketWriter() // 嵌套
.SetValue("timestamp", DateTime.Now)
.SetEnumerable("tags", new[] { "girl", "doctor" }) // 写入集合
);
var buffer = packet.GetBytes(); // 生成二进制数据包
var reader = new PacketReader(buffer); // 读取数据包
var id = reader["id"].GetValue<Guid>();
var name = (string)reader["name"].GetValue(typeof(string)); // 指定类型读取
var time = reader["data/timestamp"].GetValue<DateTime>(); // 读取子节点
var tags = reader["data/tags"].GetArray();
动态读写
var packet = new PacketWriter();
var d = (dynamic)packet;
d.id = 1024;
d.name = "Bob";
d.data.ipaddr = IPAddress.Loopback;
d.data.tags = new[] { "boy", "tall" };
var buffer = packet.GetBytes();
var reader = new PacketReader(buffer);
var r = (dynamic)reader;
var id = (int)r.id;
var name = (string)r.name;
var address = (IPAddress)r.data.ipaddr;
var tags = (string[])r.data.tags;
序列化匿名对象
var packet = PacketWriter.Serialize(new
{
id = Guid.NewGuid(),
name = "Candy",
details = new
{
age = 18,
},
});
自定义数据类
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public IEnumerable<string> Tags { get; set; }
}
自定义泛型转换器
public class PersonConverter : IPacketConverter<Person>
{
public int Length => 0; // 长度非固定, 返回零
public byte[] GetBytes(Person value)
{
if (value == null)
return new byte[0];
// 借助 PacketRawWriter, 生成固定格式数据包
var raw = new PacketRawWriter();
raw.SetValue(value.Id);
raw.SetValue(value.Name);
var tags = value.Tags;
if (tags != null)
foreach (var i in tags)
raw.SetValue(i);
return raw.GetBytes();
}
public Person GetValue(byte[] buffer, int offset, int length)
{
var p = new Person();
// 使用 PacketRawReader, 解析固定格式数据包
var raw = new PacketRawReader(buffer, offset, length);
p.Id = raw.GetValue<int>();
p.Name = raw.GetValue<string>();
var tags = new List<string>();
while (raw.Any)
tags.Add(raw.GetValue<string>());
p.Tags = tags;
return p;
}
byte[] IPacketConverter.GetBytes(object value)
{
return GetBytes((Person)value);
}
object IPacketConverter.GetValue(byte[] buffer, int offset, int length)
{
return GetValue(buffer, offset, length);
}
}
使用自定义转换器词典读写数据
var p = new Person
{
Id = 2048,
Name = "Emma",
Tags = new[] { "cute" },
};
var customConverters = new Dictionary<Type, IPacketConverter>()
{
[typeof(Person)] = new PersonConverter(),
};
var packet = PacketWriter.Serialize(p, customConverters);
var buffer = packet.GetBytes();
var reader = new PacketReader(buffer, customConverters);
var person = reader.GetValue<Person>();
F# 集合 List Map Set
open Mikodev.Network
open System
[<EntryPoint>]
let main argv =
// list
let list = [ for i in 0..9 do yield i * i ]
let ta = PacketConvert.Serialize(list)
let ra = PacketConvert.Deserialize<int list>(ta)
// map
let map = seq { for i in 0..9 do yield (i, sprintf "%x" (i * i)) } |> Map
let tb = PacketConvert.Serialize(map)
let rb = PacketConvert.Deserialize<Map<int, string>>(tb)
// set
let random = new Random()
let set = seq { for i in 0..9 do yield random.Next() } |> Set
let tc = PacketConvert.Serialize(set)
let rc = PacketConvert.Deserialize<Set<int>>(tc)
0
记录
open Mikodev.Network
open System
type Book = { id : Guid; title : string; tags : string list }
[<EntryPoint>]
let main argv =
let blank = { id = Guid.NewGuid(); title = "Way to bug"; tags = [ "exciting"; "marvelous" ] }
let buffer = PacketConvert.Serialize(blank)
let book = PacketConvert.Deserialize<Book>(buffer)
0