【问题标题】:Does C# support automated custom serialization/deserialization via attributes?C# 是否支持通过属性自动自定义序列化/反序列化?
【发布时间】:2020-01-09 15:04:17
【问题描述】:

围绕这个谷歌搜索,我从旧的 .NET 版本等中得到了很多不同的结果。

给定一个消息协议,例如:

  • 字节 0-1:消息类型 ID
  • 字节 2:消息号
  • 字节 3:有效负载大小
  • 字节 4...n-1:有效负载数据
  • 字节 n,n+1:校验和

我想编写一个 C# 类 Message,它可以使用 byte[] 进行序列化和反序列化,理想情况下它的核心可能是这样的(我使用属性,但如果重要,成员就可以了)

class Message
{
 public Int16 Type {get; set;}
 public byte Number {get; set;}
 public byte PayloadSize {get; set;}
 public byte[] Payload{get; set;}
 public Int16 CheckSum {get; set;}
}

当然,编写代码来做到这一点很容易,但我知道 .NET 确实具有一些自动(反)序列化功能,可以很好地避免在枯燥的样板代码中出现编码错误。但是我需要保证顺序等,以便遵循协议。

现代 .NET Framework (4.x) 是否允许自动执行此操作?如果可以,它是什么?例如,如何控制属性排序?我将如何实际从/到byte[] 实例化和序列化对象?

我应该补充一点,我知道可以使用反射来编写这种东西,但是一个比它解决的问题更多的解决方案并没有多大用处。除非经过充分测试,否则我也不热衷于使用某些代码库,这确实是关于内置 C# 功能的问题。

【问题讨论】:

标签: c# .net serialization


【解决方案1】:

我想到了这样的叠加层

    [StructLayout(LayoutKind.Explicit, Size = 128)]
    struct Message
    {
        [FieldOffset(0)]
        public byte[] data;
        [FieldOffset(0)]
        public Int16 Type;
        [FieldOffset(2)]
        public byte Number;
        [FieldOffset(3)]
        public byte PayloadSize;
        [FieldOffset(4)]
        public Int16 type;
        [FieldOffset(6)]
        public byte[] Payload;
        [FieldOffset(126)]
        public Int16 CheckSum;
    }

【讨论】:

  • 如果有效载荷中有 0 个字节或 121 个字节怎么办?
  • 如果负载是可变大小的,那么 CRC 应该是负载的一部分,而不是单独的属性。
  • PayloadSizeBytes 4...n-1 似乎就是这个意思,那么这确实是一个选项。然后 OP 需要代码从有效负载中获取校验和字节,并记住在要读取有效负载时跳过有效负载的最后两个字节。
  • 在可变大小的元素之后添加元素确实会搞砸这一点,尽管这是一个真实的例子。不过,在更严格的情况下似乎是一个很好的解决方案。这就像一个 C 联合,有趣的想法我根本没有考虑过实际上强制它是内存对齐而不是自动序列化逻辑
  • 我在几天前的另一篇文章中提到了这一点。不知道为什么其他人以前没有这样做过。通常变量项是最后一项(或者变量项之前有一个长度)。这些类型结构在 unix 和现在的 linux 中被大量使用。
猜你喜欢
  • 1970-01-01
  • 2017-04-06
  • 2011-12-23
  • 2010-10-31
  • 1970-01-01
  • 1970-01-01
  • 2015-07-27
  • 1970-01-01
相关资源
最近更新 更多