Wjybxx.Dson.Codec 2.2.0-rc1

This is a prerelease version of Wjybxx.Dson.Codec.
There is a newer version of this package available.
See the version list below for details.
dotnet add package Wjybxx.Dson.Codec --version 2.2.0-rc1                
NuGet\Install-Package Wjybxx.Dson.Codec -Version 2.2.0-rc1                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Wjybxx.Dson.Codec" Version="2.2.0-rc1" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Wjybxx.Dson.Codec --version 2.2.0-rc1                
#r "nuget: Wjybxx.Dson.Codec, 2.2.0-rc1"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Wjybxx.Dson.Codec as a Cake Addin
#addin nuget:?package=Wjybxx.Dson.Codec&version=2.2.0-rc1&prerelease

// Install Wjybxx.Dson.Codec as a Cake Tool
#tool nuget:?package=Wjybxx.Dson.Codec&version=2.2.0-rc1&prerelease                

Dson序列化

Dson有许多强大的特性,你如果只是简单使用Dson,那和普通的序列化组件差不多,可能还没那么方便,因为还要做点准备工作; 如果与Dson深度集成,Dson将提供许多强大的功能。

ps: Readme文档暂时复制了Java的内容,Csharp的序列化将包含Java的所有功能, 传送门Java-Code

特性一览

  1. 支持泛型
  2. 默认值可选写入
  3. 指定数字字段的编码格式(apt)
  4. 支持多态解析,指定指定默认解码类型(apt)
  5. 字段级别的读写代理(核心功能)(apt)
  6. 序列化钩子方法(apt)
  7. 单例支持(apt)
  8. 为外部库类生成Codec(apt)
  9. 外部静态代理(apt)

目前仅支持了Codec的核心编解码功能,可通过手写Codec实现对象的编解码, APT相关功能将由Dson-Apt模块实现。

有限泛型支持

Csharp是真实泛型,为方便使用,Dson库对泛型支持了完整支持 —— 使用上有点配置工作量。
支持泛型的优点:

  1. 类型自解释,精准编解码
  2. 跨语言通信支持 -- 更多是共享配置文件。

注意:虽然C#库提供了完整的泛型支持,在涉及公共文件时,应当限制泛型的使用 —— 避免泛型参数为泛型, 否则影响跨语言时的兼容性。

默认值可选写入

对于基础类型 int32,int64,float,double,bool,可以通过Options.appendDef控制是否写入写入默认值; 对于引用类型,可以通过Options.appendNull控制是否写入null值。

如果数据结构中有大量的可选属性(默认值),那么不写入默认只和null可以很好的压缩数据包。

指定数字字段的编码格式

Dson集成了Protobuf的组件,支持数字的varintunitsintfixed4种编码格式,你可以简单的通过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提供了writeObjectreadObjectconstructorafterDecodebeforeEncode5种默认的钩子调用支持。

  1. 如果用户定义了包含指定writer的writeObject方法,在编码时将自动调用该方法。
  2. 如果用户定义了包含指定reader的readObject方法,在解码时将自动调用
  3. 如果用户定义了包含指定reader的构造方法,在解码时将自动调用 - 通常用于读取final字段。
  4. 如果用户定义了包含options的afterDecode方法,在解码的末尾将自动调用 - 通常用于处理缓存字段。
  5. 如果用户定义了包含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,通过CodecLinkerGroupCodecLinker两个注解实现。


@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:

  1. CodecLinkerBean同样会为目标Bean生成Codec类。
  2. 你可以将CodecLinkerBean看做目标Bean的外部配置类。
  3. 注解的使用实例可参考BigCat项目。

Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.

Version Downloads Last updated
2.3.0 104 10/28/2024
2.2.1 259 8/25/2024
2.2.0 163 8/21/2024
2.2.0-rc3 87 7/31/2024
2.2.0-rc2 100 7/21/2024
2.2.0-rc1 106 7/14/2024
2.1.0-rc1 70 5/20/2024
2.1.0-alpha 86 5/15/2024