Wjybxx.Dson.Codec
2.1.0-rc1
See the version list below for details.
dotnet add package Wjybxx.Dson.Codec --version 2.1.0-rc1
NuGet\Install-Package Wjybxx.Dson.Codec -Version 2.1.0-rc1
<PackageReference Include="Wjybxx.Dson.Codec" Version="2.1.0-rc1" />
paket add Wjybxx.Dson.Codec --version 2.1.0-rc1
#r "nuget: Wjybxx.Dson.Codec, 2.1.0-rc1"
// Install Wjybxx.Dson.Codec as a Cake Addin #addin nuget:?package=Wjybxx.Dson.Codec&version=2.1.0-rc1&prerelease // Install Wjybxx.Dson.Codec as a Cake Tool #tool nuget:?package=Wjybxx.Dson.Codec&version=2.1.0-rc1&prerelease
Dson序列化
Dson有许多强大的特性,你如果只是简单使用Dson,那和普通的序列化组件差不多,可能还没那么方便,因为还要做点准备工作; 如果与Dson深度集成,Dson将提供许多强大的功能。
ps: Readme文档暂时复制了Java的内容,Csharp的序列化将包含Java的所有功能, 传送门Java-Code。
特性一览
- 支持泛型
- 默认值可选写入
- 指定数字字段的编码格式(apt)
- 支持多态解析,指定指定默认解码类型(apt)
- 字段级别的读写代理(核心功能)(apt)
- 序列化钩子方法(apt)
- 单例支持(apt)
- 为外部库类生成Codec(apt)
- 外部静态代理(apt)
目前仅支持了Codec的核心编解码功能,可通过手写Codec实现对象的编解码, APT相关功能将由Dson-Apt模块实现。
有限泛型支持
Csharp是真实泛型,为方便使用,Dson库对泛型支持了完整支持 —— 使用上有点配置工作量。
支持泛型的优点:
- 类型自解释,精准编解码
- 跨语言通信支持 -- 更多是共享配置文件。
注意:虽然C#库提供了完整的泛型支持,在涉及公共文件时,应当限制泛型的使用 —— 避免泛型参数为泛型, 否则影响跨语言时的兼容性。
默认值可选写入
对于基础类型 int32,int64,float,double,bool,可以通过Options.appendDef
控制是否写入写入默认值;
对于引用类型,可以通过Options.appendNull
控制是否写入null值。
如果数据结构中有大量的可选属性(默认值),那么不写入默认只和null可以很好的压缩数据包。
指定数字字段的编码格式
Dson集成了Protobuf的组件,支持数字的varint
、unit
、sint
、fixed
4种编码格式,你可以简单的通过DsonProperty
注解声明
字段的编码格式,而且修改编码格式不会导致兼容性问题,eg:
@DsonProperty(wireType = WireType.Uint)
public int age;
// 生成的编码代码
writer.writeInt(names_age, instance.age, WireType.UINT);
writer.writeString(names_name, instance.name);
示例中的int类型的age字段,在编码时将使用uint格式编码。
指定多态字段的实现
以字典的解码为例,一般序列化框架只能反序列化为Dictionary<K,V>
,限制了业务对数据结构的引用;但Dson支持你指定字段的实现类,eg:
@DsonProperty(impl = EnumMap.class)
public IDictionary<Sex, String> sex2NameMap3;
上面的这个Map字段在解码时就会解码为EnumMap。具体类型的集合和Map,通常不需要指定实现类,但也是可以指定的,eg:
// 未指定实现类,APT判断为具体类型,直接调用构造函数
public Int2IntOpenHashMap currencyMap1;
// 指定了实现类型,APT调用指定类的构造函数
@DsonProperty(Int2IntOpenHashMap.class)
public Int2IntMap currencyMap2;
上面的这两个Map字段都会解码为 Int2IntOpenHashMap,编解码代码都是生成的静态代码,看看生成的代码你就很容易明白这是如何实现的。
字段级别的读写代理(核心)
上面都是FieldImpl的简单用法,FieldImpl的最强大之处就在于字段级别的读写代理。
Dson的理念是:能托管的逻辑就让生成的代码负责,用户只处理特殊编解码的部分。
一个很好的编码指导是:我们写的代码越少,代码就越干净了,维护成本就越低,项目代码质量就越有保证。
与一般的序列化工具不同,Dson支持生成的代码调用用户的自定义代码,从而实现在编解码过程中用户只处理特殊字段逻辑。
举个栗子,假设一个Class有100个字段,有一个字段需要特殊解码,那么用户就可以只处理这一个字段的编解码,其余的仍然由生成的代码负责,
生成的代码在编解码该特殊字段的时候就会调用用户手写的代码。看段代码:
ps: 字段读写代理几乎可实现DsonProperty
提供的其它所有功能。
@DsonProperty(writeProxy = "writeCustom", readProxy = "readCustom")
public Object custom;
// 定义了钩子方法后,生成的Codec代码会自动调用
public void writeCustom(DsonLiteObjectWriter writer, String name) {
writer.writeObject(custom, TypeArgInfo.OBJECT);
}
public void readCustom(DsonLiteObjectReader reader, String name) {
this.custom = reader.readObject(TypeArgInfo.OBJECT);
}
我们在类中有一个Object类型的custom字段,并且通过FieldImpl声明了读写代理方法的名字, 生成的代码就会在编解码custom的时候调用用户的方法,下面是生成的代码节选:
// 解码方法
instance.currencyMap1 = reader.readObject(names_currencyMap1, CodecBeanExampleSchema.currencyMap1);
instance.currencyMap2 = reader.readObject(names_currencyMap2, CodecBeanExampleSchema.currencyMap2);
instance.readCustom(reader, names_custom);
// 编码方法
writer.writeObject(names_currencyMap1, instance.currencyMap1, CodecBeanExampleSchema.currencyMap1);
writer.writeObject(names_currencyMap2, instance.currencyMap2, CodecBeanExampleSchema.currencyMap2);
instance.writeCustom(writer, names_custom);
序列化钩子方法
Dson提供了writeObject
、readObject
、constructor
、afterDecode
、beforeEncode
5种默认的钩子调用支持。
- 如果用户定义了包含指定writer的writeObject方法,在编码时将自动调用该方法。
- 如果用户定义了包含指定reader的readObject方法,在解码时将自动调用
- 如果用户定义了包含指定reader的构造方法,在解码时将自动调用 - 通常用于读取final字段。
- 如果用户定义了包含options的afterDecode方法,在解码的末尾将自动调用 - 通常用于处理缓存字段。
- 如果用户定义了包含options的beforeEncode方法,在编码之前将自动钓鱼 - 通常用于处理缓存字段。
注意,这里仍然遵从前面的编码指导,你只需要处理特殊的字段,其它字段交给生成的代码处理即可。
// 序列化前钩子
public void beforeEncode(ConverterOptions options) {
}
// 自定义写入字段 - 紧随beforeEncode调用
public void writeObject(DsonObjectWriter writer) {
}
// 读自定义写入字段
public void readObject(DsonObjectReader reader) {
}
// 反序列化钩子
public void afterDecode(ConverterOptions options) {
if (age < 1) throw new IllegalStateException();
}
// 字段读写钩子
public void writeCustom(DsonObjectWriter writer, String name) {
}
public void readCustom(DsonObjectReader reader, String name) {
}
单例支持
Dson在ClassImpl
注解中提供了singleton
属性,当用户指定singleton
属性时,生成的Codec将简单调用给定方法返回共享实例。
@ClassImpl(singleton = "getInstance")
@DsonSerializable
public class SingletonTest {
private static final SingletonTest INST = new SingletonTest("wjybxx", 29);
public static SingletonTest getInstance() {
return INST;
}
}
为外部类生成Codec类
APT除了支持为项目中的类生成Codec外,还支持为外部库的类生成Codec,通过CodecLinkerGroup
和CodecLinker
两个注解实现。
@CodecLinkerGroup(outputPackage = "cn.wjybxx.btree.fsm")
private static class FsmLinker {
@CodecLinker(classImpl = @ClassImpl)
private ChangeStateTask<?> changeStateTask;
@CodecLinker(classImpl = @ClassImpl)
private StateMachineTask<?> stateMachineTask;
}
ps: 该注解的最佳实例可见BTree-Codec
外部静态代理
如果我们要序列化的是一个外部库的类,且期望能够参与到目标类型序列化过程中,我们就可以通过CodecLinkerBean
实现外部静态代理。
CodecLinkerBean
支持除构造函数以外的所有钩子,包括字段的读写代理。
@CodecLinkerBean(value = ThirdPartyBean2.class)
public class CodecLinkerBeanTest {
@DsonProperty(wireType = WireType.UINT)
private ThirdPartyBean2 age;
@DsonProperty(stringStyle = StringStyle.AUTO_QUOTE)
private ThirdPartyBean2 name;
// 这些钩子方法,生成的代码会自动调用
public static void beforeEncode(ThirdPartyBean2 inst, ConverterOptions options) {
}
public static void writeObject(ThirdPartyBean2 inst, DsonObjectWriter writer) {
}
public static void readObject(ThirdPartyBean2 inst, DsonObjectReader reader) {
}
public static void afterDecode(ThirdPartyBean2 inst, ConverterOptions options) {
}
}
ps:
CodecLinkerBean
同样会为目标Bean生成Codec类。- 你可以将
CodecLinkerBean
看做目标Bean的外部配置类。 - 注解的使用实例可参考BigCat项目。
Product | Versions Compatible and additional computed target framework versions. |
---|---|
.NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 is compatible. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. |
-
net6.0
- Wjybxx.Commons.Core (>= 1.0.13)
- Wjybxx.Dson (>= 2.1.2)
-
net7.0
- Wjybxx.Commons.Core (>= 1.0.13)
- Wjybxx.Dson (>= 2.1.2)
NuGet packages (2)
Showing the top 2 NuGet packages that depend on Wjybxx.Dson.Codec:
Package | Downloads |
---|---|
Wjybxx.BTree.Codec
行为树Codec包 |
|
Wjybxx.Dson.Apt
Dson注解处理器,代码生成工具 |
GitHub repositories
This package is not used by any popular GitHub repositories.