Сериализация словаря с помощью DataContractSerializer генерирует данные ниже. Как заменить d2p1:KeyValueOfintint, d2p1:Key и d2p1:Value нашими собственными атрибутами / тегами / идентификатором.
Сериализация словаря в [CashCounter],
Вывод, генерируемый после сериализации, приведен ниже
<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);
}





Вы можете управлять именами элементов, ключей и значений в словаре при сериализации в XML, создав подкласс Dictionary<TKey, TValue>, применив CollectionDataContractAttribute и установив следующие значения атрибутов:
ItemName: получает или устанавливает собственное имя для элемента пары ключ / значение словаря.
KeyName: получает или устанавливает собственное имя для элемента имени ключа словаря.
ValueName: получает или устанавливает собственное имя для элемента значения словаря.
Namespace: при необходимости получает или устанавливает пространство имен для контракта данных.
Name: при необходимости получает или устанавливает имя контракта данных для типа словаря. Это становится именем корневого элемента XML, когда словарь сериализуется как корневой объект.
(Поскольку словарь не является корневым объектом в вашей модели данных, установка этого конкретного свойства в этом случае не требуется.)
Таким образом, если вы определяете свою модель данных CashCounter следующим образом (упрощенно для удаления нерелевантных членов):
[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 будет выглядеть так:
<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>
Примечания:
Вам следует подумать о замене пространства имен чем-то постоянным.
Пространство имен является частью имя контракта данных. В настоящее время у него есть некоторое значение по умолчанию, связанное с вашим пространством имен C#, поэтому, если вы реорганизуете свой код и поместите классы в разные пространства имен C#, пространство имен контракта данных может измениться. Поскольку пространство имен контракта данных фактически публикуется в вашем WSDL, это может доставить неудобства вашим клиентам. Вы также можете использовать пространство имен в целях брендинга, включив в начало URL-адрес вашей организации.
Для дальнейшего чтения см. Что дает добавление имени и пространства имен в DataContract? и Для чего нужны пространства имен XML?.
Для документации см. Типы коллекций в контрактах данных: настройка коллекций словаря.
@MakAhmed - ну, пространство имен является частью имя контракта данных. В настоящее время у него есть некоторое значение по умолчанию, связанное с вашим пространством имен C#, поэтому, если вы реорганизуете свой код и поместите классы в разные пространства имен C#, пространство имен контракта данных может измениться. А поскольку пространство имен контракта данных фактически опубликовано в вашем WSDL, это может доставить неудобства вашим клиентам. Связанный: Что дает добавление имени и пространства имен в DataContract?.
Я полностью понимаю пространство имен. Спасибо, что указали на это.
Спасибо за ответ, опишите, что именно вы имеете в виду. Вам следует заменить пространство имен чем-то постоянным.