【问题标题】:Serialization/Deserialization without attributes in C#C#中没有属性的序列化/反序列化
【发布时间】:2018-06-14 11:02:14
【问题描述】:

我有许多类,包括对象层次结构和接口、基类等的常规设计,来自我无法修改任何代码的项目。我的项目中有另一个有效负载类,它使用组合来封装来自其他类的信息并包含有效负载类中的属性,其类型是来自其他项目的类。

现在我需要能够创建一个包含其他类实例的有效负载类的实例,并将其序列化为 Base64 字符串以进行传输。

问题是因为我无法触及其他类的代码,所以我无法添加序列化属性(对于 .NET 二进制格式化程序/protobuf-net)。我也尝试过使用没有属性的protobuf-net,但是由于对象层次太深,创建起来似乎太复杂了。

谁能告诉我在不修改现有代码的情况下继续进行序列化/反序列化部分的更好选择。

说明需求的示例代码如下所示:

void Main()
{
    var b = new B();
    b.SetStatus("This is B");

    var c = new C { Name = "C", Value = 100};

    var payload = new Payload(b, c);

    var serializedData = SerializeToString<Payload>(payload);

    serializedData.Dump();
}

private static TData DeserializeFromString<TData>(string settings)
{
    byte[] b = Convert.FromBase64String(settings);
    using (var stream = new MemoryStream(b))
    {
        var formatter = new BinaryFormatter();
        stream.Seek(0, SeekOrigin.Begin);
        return (TData)formatter.Deserialize(stream);
    }
}

private static string SerializeToString<TData>(TData settings)
{
    using (var stream = new MemoryStream())
    {
        var formatter = new BinaryFormatter();
        formatter.Serialize(stream, settings);
        stream.Flush();
        stream.Position = 0;
        return Convert.ToBase64String(stream.ToArray());
    }
}

public class A
{
    public string Id { get; set; }
    public string StatusMsg {get;protected set;}
    public virtual void SetStatus(string msg)
    {
        StatusMsg = msg;
    }
}

public class B : A
{
    public B()
    {
        Id = new Guid().ToString();
    }

    public override void SetStatus(string msg)
    {
        base.SetStatus(msg);
    }
}

public class C
{
    public string Name
    {
        get;
        set;
    }

    public Int32 Value
    {
        get;
        set;
    }
}

public class Payload
{
    public B PropertyB { get; set; }
    public C PropertyC { get; set; }

    public Payload(B b, C c)
    {
        this.PropertyB = b;
        this.PropertyC = c;
    }
}

【问题讨论】:

  • 你考虑过使用JSON.NET吗?
  • @MatthewWatson 我需要一种二进制序列化的方法,因为这需要通过网络进行,而且 JSON 太大且可读性太大
  • 所以只是序列化后压缩一下?

标签: c# serialization protobuf-net binary-serialization


【解决方案1】:

不添加配置属性,你有几个选择:

  • 使用无关紧要的序列化:XmlSerializer 或 Json.NET 可能会工作,如果你幸运的话
  • 接受诸如 protobuf-net 或其他其中之一的运行时配置工作;它可能没有您期望的那么多工作(见鬼,给我发一封包含真实代码的电子邮件,我也许可以做到)
  • 完全手动编写序列化
  • 编写一个 DTO 层 - 一个具有属性等的基本模型,与您选择的序列化程序配合得很好 - 并编写代码在两个模型之间进行映射,或者使用自动映射器等工具

就个人而言,当序列化配置变得棘手时,我的默认选项是“编写 DTO 模型”。

【讨论】:

  • 是否有任何示例代码显示了 Protobuf 的用法,而不使用任何体面嵌套的对象层次结构的属性。
【解决方案2】:

我不明白为什么 protobuf 不起作用,但如果您不介意,您可以手动进行序列化。

在这种情况下,创建一个BinaryWriter,然后编写您需要的所有内容,以便使用BinaryReader 再次反序列化它。这样做,您将获得为您的特定需求量身定制的非常紧凑的表示,而且速度也非常快。但这也需要更多的工作。通用序列化可能冗长而缓慢,但在任何情况下几乎总是首选。

但我仍然不明白为什么使用任何现有的无属性序列化方法都行不通。您可能应该首先真正理解为什么它不适用于例如 protobuf 或 JSON.NET。您提到“层次太深”。那有多深?

【讨论】:

  • 如果为 protobuf-net 的运行时配置配置一些属性等效设置的工作量太大,那么这样做也可能工作量太大
猜你喜欢
  • 1970-01-01
  • 2015-03-17
  • 2021-05-26
  • 2016-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多