【问题标题】:Custom serialisation of a Dictionary in a DataContractDataContract 中字典的自定义序列化
【发布时间】:2012-06-27 21:25:55
【问题描述】:

基本上我有一个DataContract,其中包含一个Dictionary

[DataContract]
public class MyDictionary : IDictionary<string, object> {
    [DataMember(Name = "Data")]
    protected IDictionary<string, object> Dictionary { get; private set; }

    // ...
}

这是 XML 输出的相关部分:

<Data>
 <a:KeyValueOfstringanyType>
  <a:Key>ID</a:Key>
  <a:Value i:type="s:int">2</a:Value>
 </a:KeyValueOfstringanyType>
 <a:KeyValueOfstringanyType>
  <a:Key>Value</a:Key>
  <a:Value i:type="s:int">4711</a:Value>
 </a:KeyValueOfstringanyType>
</Data>

如何在此处将输出简化为如下内容:

<Data>
  <ID i:type="s:int">2</ID>
  <Value i:type="s:int">4711</Value>
</Data>

字典键仅限于字符串,所以如果没有人想到使用非 ascii 键的愚蠢想法应该可以正常工作。我找到了属性CollectionDataContract,我离我想要的更近了一点,但是键值对将被完整保存,这会浪费内存。也许可以使用ISerializable 类,但我不确定这是否会给DataContractSerializer 带来一些麻烦。顺便说一句,该解决方案也应该适用于DataContractJsonSerializer

【问题讨论】:

  • 这不会是过早优化的情况吧?我倾向于让 DataContracts 和序列化器/反序列化器尽可能地做自己的事情以避免头痛。
  • @ChrisSinclair 可能有许多键值对,并且这些内容是使用 android 客户端以 JSON 格式读取的。到目前为止,我认为这项工作应该是有意义的。
  • 在这种情况下,您想使用 JSON 序列化程序而不是 XML 序列化程序吗?如果是这样,那么也许在其上粘贴一个 JSON 序列化程序并查看其结果可能是值得的。 (也许它已经充分优化了)另外,如果你想保留 XML,你可能需要在 ID/Value 周围有某种Entry 包装器,这样你就可以有多个 KeyValuePairs。 &lt;Data&gt;&lt;Entry&gt;&lt;ID i:type="s:int"&gt;2&lt;/ID&gt;&lt;Value i:type="s:int"&gt;4711&lt;/Value&gt;&lt;/Entry&gt;&lt;/Data&gt; 编辑:抱歉,我没有注意到您希望它与 JSON 和 XML 序列化程序一起使用的最后一句话。
  • @ChrisSinclair 我希望能够同时使用 XML 和 JSON。 JSON 也没有优化。使用Entrys 有什么好处?
  • 对 XML 的更多要求(也可能是 JSON)。您将如何序列化字典的多个条目?我想您可以将它们堆叠为 &lt;Data&gt;&lt;ID /&gt;&lt;ID /&gt;&lt;ID /&gt;&lt;Value /&gt;&lt;Value /&gt;&lt;Value /&gt;&lt;/Data&gt; 并假设它们的顺序相同,以便将 ID 条目与 Value 条目正确关联。

标签: c# xml-serialization datacontract


【解决方案1】:

您遇到的问题来自 IDictionary (在某种程度上)IEnumerable>,这就是 DataContractSerializer 序列化每个 KeyValuePair 个性的方式。

您要问的(如果我理解正确的话)是创建一个自定义序列化,为此您可以实现IXmlSerializable 接口。

使用WriteXml和ReadXml函数控制xml写入流,XmlWriter作为参数传递。

例如这个函数

public void WriteXml(XmlWriter writer)
    {
        foreach (var pair in _dictionary)
        {
            writer.WriteElementString("Key", pair.Key);
            writer.WriteElementString("Value", pair.Value.ToString());
        }
    }

会产生这个结果

<MyDictionary xmlns="http://schemas.datacontract.org/2004/07/Sandbox">
    <Key>ID</Key>
    <Value>15</Value>
    <Key>Value</Key>
    <Value>123</Value>
</MyDictionary>

假设字典中已输入了两对(ID,15 & Value, 123)。

哦,关于 JSON,有一个 IJsonSerializable,但我一直没有时间使用它。

【讨论】:

  • Unforchantly 我得到了一份新工作,我不再使用 WCF,但你的回答非常合乎逻辑且有道理。只是为了完成,您能否扩展您的示例如何实现IXmlSerializable 接口以及如何强制使用此序列化程序。 +1 到目前为止你的工作。
猜你喜欢
  • 1970-01-01
  • 2011-04-30
  • 2012-03-31
  • 2019-01-25
  • 1970-01-01
  • 2021-07-14
  • 1970-01-01
  • 2014-09-01
相关资源
最近更新 更多