如何使用 DataContractSerializer 自定义字典序列化? [英] How to customize dictionary serialization with DataContractSerializer?

查看:38
本文介绍了如何使用 DataContractSerializer 自定义字典序列化?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 DataContractSerializer 进行字典序列化生成以下数据.如何用我们自己的属性/标签/标识符替换 d2p1:KeyValueOfintd2p1:Keyd2p1:Value.

Dictionary serialization with DataContractSerializer generate below data. How to replace d2p1:KeyValueOfintint, d2p1:Key and d2p1:Value with our own attributes / tags / identifier.

在[CashCounter]中序列化字典,

Serializing Dictionary in [CashCounter],

序列化后的输出生成如下

Output Generate after Serialization given below

<CashCounter xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DictionarySerlization">
<BankNote xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <d2p1:KeyValueOfintint>
        <d2p1:Key>10</d2p1:Key>
        <d2p1:Value>6</d2p1:Value>
    </d2p1:KeyValueOfintint>
    <d2p1:KeyValueOfintint>
        <d2p1:Key>5</d2p1:Key>
        <d2p1:Value>10</d2p1:Value>
    </d2p1:KeyValueOfintint>
</BankNote>
<TotalCount>16</TotalCount>
<TotalSum>110</TotalSum>
</CashCounter>

<小时>

static void Main(string[] args) {
        CashCounter cashCounter = addCashCounter();
        string serilizedData = GetXml(cashCounter);
}

private static CashCounter addCashCounter() {
        CashCounter cashCounter = CreateCounter();

        for(var i = 0; i < 6; i++) { cashCounter = incrementCountAmount(cashCounter, 10); }

        for(var i = 0; i < 10; i++) { cashCounter = incrementCountAmount(cashCounter, 5); }

        return cashCounter;
}

private static CashCounter CreateCounter()
{
        var cashCounter = new CashCounter
        {
            BanknotesCount = new Dictionary<int, int>(),
            TotalSum = 0,
            TotalCount = 0
        };
        return cashCounter;
}

private static CashCounter incrementCountAmount(CashCounter cashCounter, int amount){
        const int count = 1;
        cashCounter.TotalCount += count;
        cashCounter.TotalSum += amount * count;
        if (cashCounter.BanknotesCount.ContainsKey(amount))
        {
            cashCounter.BanknotesCount[amount] += count;
        }
        else
        {
            cashCounter.BanknotesCount.Add(amount, count);
        }
        return cashCounter;
}

public static string GetXml<T>(T obj, DataContractSerializer serializer)
{
        using (var textWriter = new StringWriter())
        {
            var settings = new XmlWriterSettings {OmitXmlDeclaration = true,Indent = true, IndentChars = "    " };
            using (var xmlWriter = XmlWriter.Create(textWriter, settings))
            {
                serializer.WriteObject(xmlWriter, obj);
            }
            return textWriter.ToString();
        }
}

public static string GetXml<T>(T obj)
{
        var serializer = new DataContractSerializer(typeof(T));
        return GetXml(obj, serializer);
}

推荐答案

可以通过子类化Dictionary来控制序列化为XML时字典的item、key和value元素名称,应用 CollectionDataContractAttribute,并设置以下属性值:

You can control the item, key and value element names of a dictionary when serialized to XML by subclassing Dictionary<TKey, TValue>, applying CollectionDataContractAttribute, and setting the following attribute values:

  • ItemName:获取或设置字典键/值对元素的自定义名称.

  • ItemName: gets or sets a custom name for a dictionary key/value pair element.

KeyName:获取或设置字典键名元素的自定义名称.

KeyName: gets or sets a custom name for a dictionary key name element.

ValueName:获取或设置字典值元素的自定义名称.

ValueName: gets or sets a custom name for a dictionary value element.

Namespace:如果需要,获取或设置数据协定的命名空间.

Namespace: if needed, gets or sets a namespace for the data contract.

Name:如果需要,获取或设置字典类型的数据协定名称.当字典被序列化为根对象时,这将成为 XML 根元素名称.

Name: if needed, gets or sets the data contract name for the dictionary type. This becomes the XML root element name when the dictionary is serialized as the root object.

(由于字典不是数据模型中的根对象,因此在这种情况下不需要设置此特定属性.)

(Since the dictionary is not the root object in your data model, setting this particular property is not needed in this case.)

因此,如果您按如下方式定义 CashCounter 数据模型(简化为删除不相关的成员):

Thus, if you define your CashCounter data model as follows (simplified to remove irrelevant members):

[DataContract(Namespace = "http://schemas.datacontract.org/2004/07/DictionarySerlization")]
public class CashCounter
{
    [DataMember]
    public BankNoteDictionary BankNote { get; set; }
}

[CollectionDataContract(ItemName = "MyItemName", KeyName = "MyKeyName", ValueName = "MyValueName",
    Namespace = "http://schemas.datacontract.org/2004/07/DictionarySerlization")]
public class BankNoteDictionary : Dictionary<int, int>
{
}

生成的 XML 将如下所示:

The resulting XML will look like:

<CashCounter xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/DictionarySerlization">
  <BankNote>
    <MyItemName>
      <MyKeyName>10</MyKeyName>
      <MyValueName>6</MyValueName>
    </MyItemName>
    <MyItemName>
      <MyKeyName>5</MyKeyName>
      <MyValueName>10</MyValueName>
    </MyItemName>
  </BankNote>
</CashCounter>

注意事项:

  • 你应该考虑用一些永久的东西替换命名空间.

  • You should consider replacing the namespace with something permanent.

命名空间是 数据合同名称.目前它有一些与你的 c# 命名空间相关的默认值,所以如果你重构你的代码并将类放入不同的 c# 命名空间,数据协定命名空间可能会改变.由于数据协定命名空间实际上是在您的 WSDL 中发布的,这可能会给您的客户带来麻烦.您可能还希望通过在开头包含您组织的 URL 来使用命名空间进行品牌推广.

The namespace is part of the data contract name. Currently it has some default value related to your c# namespace, so if you refactor your code and put classes into different c# namespaces, the data contract namespace might change. Since the data contract namespace is actually published in your WSDL that could be a nuisance for your customers. You may also want to use the namespace for branding purposes by including your organization's URL at the beginning.

有关进一步阅读,请参阅将名称和命名空间添加到 DataContract 有何作用?什么是 XML 命名空间?.

For further reading see What does adding Name and Namespace to DataContract do? and What are XML namespaces for?.

有关文档,请参阅数据契约中的集合类型:自定义字典集合.

For documentation see Collection Types in Data Contracts: Customizing Dictionary Collections.

这篇关于如何使用 DataContractSerializer 自定义字典序列化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆