我已经能够以这种方式序列化IEnumerable:
[XmlArray("TRANSACTIONS")]
[XmlArrayItem("TRANSACTION", typeof(Record))]
public IEnumerable<BudgetRecord> Records
{
get
{
foreach(Record br in _budget)
{
yield return br;
}
}
}
然而,我意识到现在我需要一个包含集合Dictionary<string, RecordCollection>
的字典(RecordCollection实现IEnumerable)。
我怎样才能做到这一点?
答案 0 :(得分:12)
查看以下博客文章
和这个(不是英文,但代码很有用)
答案 1 :(得分:9)
我已经使用了以下一段时间了。它最初来自here。
namespace SerializeDictionary
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
/// <summary>
/// Represents an XML serializable collection of keys and values.
/// </summary>
/// <typeparam name="TKey">The type of the keys in the dictionary.</typeparam>
/// <typeparam name="TValue">The type of the values in the dictionary.</typeparam>
[Serializable]
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
/// <summary>
/// The default XML tag name for an item.
/// </summary>
private const string DefaultItemTag = "item";
/// <summary>
/// The default XML tag name for a key.
/// </summary>
private const string DefaultKeyTag = "key";
/// <summary>
/// The default XML tag name for a value.
/// </summary>
private const string DefaultValueTag = "value";
/// <summary>
/// The XML serializer for the key type.
/// </summary>
private static readonly XmlSerializer keySerializer = new XmlSerializer(typeof(TKey));
/// <summary>
/// The XML serializer for the value type.
/// </summary>
private static readonly XmlSerializer valueSerializer = new XmlSerializer(typeof(TValue));
/// <summary>
/// Initializes a new instance of the
/// <see cref="SerializableDictionary<TKey, TValue>"/> class.
/// </summary>
public SerializableDictionary()
{
}
/// <summary>
/// Initializes a new instance of the
/// <see cref="SerializableDictionary<TKey, TValue>"/> class.
/// </summary>
/// <param name="info">A
/// <see cref="T:System.Runtime.Serialization.SerializationInfo"/> object
/// containing the information required to serialize the
/// <see cref="T:System.Collections.Generic.Dictionary`2"/>.
/// </param>
/// <param name="context">A
/// <see cref="T:System.Runtime.Serialization.StreamingContext"/> structure
/// containing the source and destination of the serialized stream
/// associated with the
/// <see cref="T:System.Collections.Generic.Dictionary`2"/>.
/// </param>
protected SerializableDictionary(SerializationInfo info, StreamingContext context) : base(info, context)
{
}
/// <summary>
/// Gets the XML tag name for an item.
/// </summary>
protected virtual string ItemTagName
{
get
{
return DefaultItemTag;
}
}
/// <summary>
/// Gets the XML tag name for a key.
/// </summary>
protected virtual string KeyTagName
{
get
{
return DefaultKeyTag;
}
}
/// <summary>
/// Gets the XML tag name for a value.
/// </summary>
protected virtual string ValueTagName
{
get
{
return DefaultValueTag;
}
}
/// <summary>
/// Gets the XML schema for the XML serialization.
/// </summary>
/// <returns>An XML schema for the serialized object.</returns>
public XmlSchema GetSchema()
{
return null;
}
/// <summary>
/// Deserializes the object from XML.
/// </summary>
/// <param name="reader">The XML representation of the object.</param>
public void ReadXml(XmlReader reader)
{
var wasEmpty = reader.IsEmptyElement;
reader.Read();
if (wasEmpty)
{
return;
}
try
{
while (reader.NodeType != XmlNodeType.EndElement)
{
this.ReadItem(reader);
reader.MoveToContent();
}
}
finally
{
reader.ReadEndElement();
}
}
/// <summary>
/// Serializes this instance to XML.
/// </summary>
/// <param name="writer">The XML writer to serialize to.</param>
public void WriteXml(XmlWriter writer)
{
foreach (var keyValuePair in this)
{
this.WriteItem(writer, keyValuePair);
}
}
/// <summary>
/// Deserializes the dictionary item.
/// </summary>
/// <param name="reader">The XML representation of the object.</param>
private void ReadItem(XmlReader reader)
{
reader.ReadStartElement(this.ItemTagName);
try
{
this.Add(this.ReadKey(reader), this.ReadValue(reader));
}
finally
{
reader.ReadEndElement();
}
}
/// <summary>
/// Deserializes the dictionary item's key.
/// </summary>
/// <param name="reader">The XML representation of the object.</param>
/// <returns>The dictionary item's key.</returns>
private TKey ReadKey(XmlReader reader)
{
reader.ReadStartElement(this.KeyTagName);
try
{
return (TKey)keySerializer.Deserialize(reader);
}
finally
{
reader.ReadEndElement();
}
}
/// <summary>
/// Deserializes the dictionary item's value.
/// </summary>
/// <param name="reader">The XML representation of the object.</param>
/// <returns>The dictionary item's value.</returns>
private TValue ReadValue(XmlReader reader)
{
reader.ReadStartElement(this.ValueTagName);
try
{
return (TValue)valueSerializer.Deserialize(reader);
}
finally
{
reader.ReadEndElement();
}
}
/// <summary>
/// Serializes the dictionary item.
/// </summary>
/// <param name="writer">The XML writer to serialize to.</param>
/// <param name="keyValuePair">The key/value pair.</param>
private void WriteItem(XmlWriter writer, KeyValuePair<TKey, TValue> keyValuePair)
{
writer.WriteStartElement(this.ItemTagName);
try
{
this.WriteKey(writer, keyValuePair.Key);
this.WriteValue(writer, keyValuePair.Value);
}
finally
{
writer.WriteEndElement();
}
}
/// <summary>
/// Serializes the dictionary item's key.
/// </summary>
/// <param name="writer">The XML writer to serialize to.</param>
/// <param name="key">The dictionary item's key.</param>
private void WriteKey(XmlWriter writer, TKey key)
{
writer.WriteStartElement(this.KeyTagName);
try
{
keySerializer.Serialize(writer, key);
}
finally
{
writer.WriteEndElement();
}
}
/// <summary>
/// Serializes the dictionary item's value.
/// </summary>
/// <param name="writer">The XML writer to serialize to.</param>
/// <param name="value">The dictionary item's value.</param>
private void WriteValue(XmlWriter writer, TValue value)
{
writer.WriteStartElement(this.ValueTagName);
try
{
valueSerializer.Serialize(writer, value);
}
finally
{
writer.WriteEndElement();
}
}
}
}
答案 2 :(得分:6)
请尝试这种替代方法:
void Main()
{
var source=
new TestClass()
{
GroupTestTyped=
new Dictionary<string, int> { {"A", 23}, {"B", 40} }
};
using (var writer = XmlWriter.Create("c:\\test1.xml"))
(new XmlSerializer(typeof(TestClass))).Serialize(writer, source);
}
[Serializable]
public class DemoElementClass
{
public string Key { get; set; }
public int Value { get; set; }
}
[Serializable]
public class TestClass
{
public TestClass() { }
[XmlArray]
[XmlArrayItem(ElementName = "ElementTest")]
public List<DemoElementClass> GroupTest { get; set; }
[XmlIgnore]
public Dictionary<string, int> GroupTestTyped
{
get { return GroupTest.ToDictionary(x=> x.Key, x => x.Value); }
set { GroupTest = value.Select(x => new DemoElementClass {Key = x.Key, Value = x.Value}).ToList(); }
}
}
这里是xml结果:
<?xml version="1.0" encoding="utf-8"?>
<TestClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<GroupTest>
<ElementTest>
<Key>A</Key>
<Value>23</Value>
</ElementTest>
<ElementTest>
<Key>B</Key>
<Value>40</Value>
</ElementTest>
</GroupTest>
</TestClass>
答案 3 :(得分:4)
这是基于Gildors答案的更短版本:
[XmlElement("Dictionary")]
public List<KeyValuePair<string, string>> XMLDictionaryProxy
{
get
{
return new List<KeyValuePair<string, string>>(this.Dictionary);
}
set
{
this.Dictionary = new Dictionary<string, string>();
foreach (var pair in value)
this.Dictionary[pair.Key] = pair.Value;
}
}
[XmlIgnore]
public Dictionary<string, string> Dictionary
{
get; set;
}
享受。
答案 4 :(得分:0)
如果您正在学习C#
,则最好使用所需的逻辑来创建一个类。在此示例中,我制作了一个ProgressiveTax
对象,可以调用.Evaluate()
来计算税金。
您还可以写入或读取XML
字符串(可以写入文件)
例如,首先从提供的PAYE
信息中填充税级并将其保存到文件PAYE.xml
中。然后,忘记税级(超出{ }
的范围)。然后读取文件以从文件中填充税表
static class Program
{
static void Main(string[] args)
{
{
// create a tax table and save it to a file
var tax = ProgressiveTax.PAYE();
File.WriteAllText("PAYE.xml", tax.ToXml());
}
{
// read a tax table from a file
var tax = ProgressiveTax.FromXml(File.ReadAllText("PAYE.xml"));
// use the tax table
var x = tax.Evaluate(42250m);
Debug.WriteLine($"Tax={x}");
}
}
}
xml文件如下所示,可以手动编辑该文件,也可以从数据库/网络服务生成该文件。
<?xml version="1.0" encoding="utf-16"?>
<ProgressiveTax xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Credit="2400">
<Brackets>
<Bracket>
<Item1>0</Item1>
<Item2>0.1</Item2>
</Bracket>
<Bracket>
<Item1>24000</Item1>
<Item2>0.15</Item2>
</Bracket>
<Bracket>
<Item1>40667</Item1>
<Item2>0.2</Item2>
</Bracket>
<Bracket>
<Item1>57334</Item1>
<Item2>0.25</Item2>
</Bracket>
</Brackets>
</ProgressiveTax>
和实际保存税款信息并计算税款的类
public class ProgressiveTax
{
public ProgressiveTax()
{
this.Table = new SortedDictionary<decimal, float>();
}
public ProgressiveTax(SortedDictionary<decimal, float> table)
{
this.Table = table;
}
public static ProgressiveTax PAYE()
{
var tax = new ProgressiveTax();
tax.Credit = 2400m;
tax.Table[0m] = 0.1f;
tax.Table[24000m] = 0.15f;
tax.Table[40667m] = 0.20f;
tax.Table[57334m] = 0.25f;
return tax;
}
public string ToXml()
{
var fs = new StringWriter();
var xs = new XmlSerializer(typeof(ProgressiveTax));
xs.Serialize(fs, this);
fs.Close();
return fs.ToString();
}
public static ProgressiveTax FromXml(string xml)
{
var fs = new StringReader(xml);
var xs = new XmlSerializer(typeof(ProgressiveTax));
var tax = xs.Deserialize(fs) as ProgressiveTax;
fs.Close();
return tax;
}
[XmlAttribute]
public decimal Credit { get; set; }
[XmlIgnore()]
SortedDictionary<decimal, float> Table { get; }
[XmlArrayItem(ElementName = "Bracket")]
public (decimal lower, float rate)[] Brackets
{
get
{
var parts = new (decimal lower, float rate)[Table.Count];
int index = 0;
foreach (var item in Table)
{
parts[index++] = (item.Key, item.Value);
}
return parts;
}
set
{
Table.Clear();
foreach (var (lower, rate) in value)
{
Table[lower] = rate;
}
}
}
public decimal Evaluate(decimal income)
{
decimal result = -Credit;
foreach (var item in Table.Reverse())
{
if (item.Key <= income)
{
Debug.WriteLine($"Assess {item.Value:P2} tax on {income - item.Key}");
result += (decimal)( item.Value * (float) (income - item.Key));
income = item.Key;
}
}
return Math.Max(0m, result);
}
}
该示例程序在调试器中产生以下输出。
Assess 20.00% tax on 1583
Assess 15.00% tax on 16667
Assess 10.00% tax on 24000
Tax=2816.65
如果您将1583 + 16667 + 24000 = 42250
的总收入相加。由于这是一种累进税,因此将使用上述税率和金额,然后将2400记入贷方。同样,结果也不一定是0或正数。
答案 5 :(得分:0)
这个 SerializableDictionary
类可以像普通的 Dictionary
一样使用,并且可以是 Serialize()
SerializableDictionary.cs
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
/// <summary>
/// Base on https://weblogs.asp.net/pwelter34/444961
/// </summary>
/// <typeparam name="TKey"></typeparam>
/// <typeparam name="TValue"></typeparam>
[XmlRoot("dictionary")]
public class SerializableDictionary<TKey, TValue> : Dictionary<TKey, TValue>, IXmlSerializable
{
// XmlSerializer.Deserialize() will create a new Object, and then call ReadXml()
// So cannot use instance field, use class field.
public static string itemTag = "item";
public static string keyTag = "key";
public static string valueTag = "value";
public XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
if (reader.IsEmptyElement)
return;
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
reader.ReadStartElement();
// IsStartElement() will call MoveToContent()
// reader.MoveToContent();
while (reader.IsStartElement(itemTag))
{
reader.ReadStartElement(itemTag);
reader.ReadStartElement(keyTag);
TKey key = (TKey)keySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement(valueTag);
TValue value = (TValue)valueSerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadEndElement();
this.Add(key, value);
// IsStartElement() will call MoveToContent()
// reader.MoveToContent();
}
reader.ReadEndElement();
}
public void WriteXml(XmlWriter writer)
{
var keySerializer = new XmlSerializer(typeof(TKey));
var valueSerializer = new XmlSerializer(typeof(TValue));
foreach (var kvp in this)
{
writer.WriteStartElement(itemTag);
writer.WriteStartElement(keyTag);
keySerializer.Serialize(writer, kvp.Key);
writer.WriteEndElement();
writer.WriteStartElement(valueTag);
valueSerializer.Serialize(writer, kvp.Value);
writer.WriteEndElement();
writer.WriteEndElement();
}
}
}
Demo.cs
using System;
using System.IO;
using System.Xml.Serialization;
//[XmlRoot("AnimalDictionary")]
public class SDict : SerializableDictionary<string, string>
{
}
namespace Test
{
public class Program
{
static void Main(string[] args)
{
var dict = new SDict();
//SDict.itemTag = "AnimalCount";
//SDict.keyTag = "Type";
//SDict.valueTag = "Count";
dict.Add("Cat", "1");
dict.Add("Dog", "2");
foreach (var kvp in dict)
Console.WriteLine(kvp);
XmlSerializer serializer = new XmlSerializer(typeof(SDict));
using (var writer = new StreamWriter("dict.xml"))
{
serializer.Serialize(writer, dict);
}
Console.WriteLine("\nXML File:");
Console.WriteLine(File.ReadAllText("dict.xml"));
using (var reader = new StreamReader("dict.xml"))
{
dict = serializer.Deserialize(reader) as SDict;
}
Console.WriteLine("\nAfter Deserialize");
foreach (var kvp in dict)
Console.WriteLine(kvp);
Console.ReadLine();
}
}
}