C# 类型序列化不作为键值对的集合

Posted

技术标签:

【中文标题】C# 类型序列化不作为键值对的集合【英文标题】:C# type serialization not as a collection of key value pairs 【发布时间】:2019-04-25 13:49:11 【问题描述】:

我有一个类,当序列化时,我想作为没有键值对的单个字符串返回。一个字符串变成一个字符串。一个 int 变成一个 int。如何让我的类变成字符串?

查看 DataContractSerializable,看起来这是不可能的。 SerializationInfo.AddValue(name, value) 设置强制您的整个对象采用键值方法。我只想返回“A and B”

[DataContract]
public class MyObject

    public int A  get; set; 
    public int B  get; set; 

例如,当使用 DataContractJsonSerializer 进行序列化时,我希望它是:

4 and 2

没有


    "A": 4,
    "B": 2

假设我有一个使用这两种自定义类型的父类:

[DataContract]
public class Parent

    [DataMember]
    public MyObject One  get; set; 

    [DataMember]
    public MyObject Two  get; set; 

我想这样序列化:


    "One": "4 and 2",
    "Two": "6 and 8"

相反,我似乎唯一能做到的是:


    "One": 
        "A": 4,
        "B": 2
    ,
    "Two": 
        "A": 6,
        "B": 8
    

唯一可行的解​​决方案是在 Parent 上添加自定义序列化,相应地设置 One 和 Two,但我不想这样做,我希望我的新类在任何地方都被序列化为字符串。

我可以将一个类型序列化为单个返回值吗?还是除了 int 和 string 等内置类型之外的所有类型都必须序列化为对象?

【问题讨论】:

docs.microsoft.com/en-us/dotnet/standard/serialization/… 作为记录,这是我一直在阅读的文档。它没有(据我所知)指示如何执行此操作。只有键值对,因为它假设一种类型的所有序列化都分解为一个或多个 DataMembers。 【参考方案1】:

您可以简单地添加一个 get 属性,以任何您喜欢的方式将属性作为字符串返回...

public class MyObject

    public int A  get; set; 
    public int B  get; set; 
    public string MyNewStringAttribute 
       get
          return A + " and " + B;
       
    

然后,当您可以使用数组、linq 等中的新属性从控制器序列化时。

【讨论】:

你的意思是序列化它,所以你有: ` "One": "A": 4, "B": 2, "C": "4 and 2" , "Two" : "A": 6, "B": 8, "C": "6 and 8" ` 这不是我们想要的体验。 [DataContract] public class Parent [DataMember] public MyObject One get return MyNewStringAttribute; ... [DataMember] public MyObject 二 get return MyNewStringAttribute; ... > 唯一可行的解​​决方案是在 Parent 上添加自定义序列化,相应地设置 One 和 Two,但我不想这样做,我希望我的新类被序列化为到处都是字符串。【参考方案2】:

我的回答:你不能。

父类MyObject 必须实现ISerializable 以提供类本身的自定义序列化。这将正确序列化类的责任置于希望使用它的每个类身上,这是一种不良体验,并突出了受支持的 .NET 自定义序列化器策略中的严重设计缺陷。

[Serializable]
public class Parent : ISerializable

    public MyObject One  get; set; 

    public MyObject Two  get; set; 

    public (SerializerInfo info, SerializerContext context)
    
        string oneString = info.GetString("One");
        One = new MyObject(oneString);

        string twoString = info.GetString("Two");
        Two = new MyObject(twoString);
    

    public override void GetObjectData(SerializerInfo info, SerializerContext context)
    
        info.AddValue("One", One.ToString());
        info.AddValue("Two", Two.ToString());
    

Grumble 发牢骚...将此添加到 .NET 出错的长长列表中。所有东西的静态/非接口类,默认情况下使框架不可测试,而无需为所有东西创建即插即用的包装器。具有有损 MSIL/符号的编译器。我可以继续说下去。

【讨论】:

以上是关于C# 类型序列化不作为键值对的集合的主要内容,如果未能解决你的问题,请参考以下文章

键值对的聚类

JS基础 Map是一组键值对的结构

调试 C# 时为啥不能更改字典键值对的计数?

将控件绑定到键值对的动态集合

重温 C# 字典Dictionary类

Java源码分析集合部分总结