In a particular application, we need to persist an object in memory that is instantiated from a template class and cannot be saved to a database, where only the template for this object is stored.
Because of the use of dictionary to generics, while XmlSerializer does not support the default generic dictionary, I have found some information and implemented in three different ways in this article. The Convention in this article:
Scenario 1: Dictionary of Non-serialized generics
Scenario 2: Define a dictionary that supports generics
Scenario 3: Let each class implement the IXmlSerializable interface
Article content:
1. Class diagram and the association between classes
2. Scenario 1: Dictionary of Non-serialized generics
3. Option 2: Define a dictionary that supports generics
4. Option 3: Let each class implement the IXmlSerializable interface
5. Summary
1. Class diagram and the association between classes
Compensation template Paytemplate, it through the dictionary<int, payitemtemplate> maintain a number of compensation column template payitemtemplate.
And a payitemtemplate through Dictionary<int, Payitemtemplate> records the payitemtemplate that used it.
Therefore, paytemplate and payitemtemplate are a pair of multiple associations; The payitemtemplate is a one-to-many self-association.
The class associations in scenario 1,2,3 are similar, and there is no repetition here. Detailed differences can be downloaded from the source code view at the end of this article.
2. Scenario 1: Dictionary of Non-serialized generics
Now that we know that generics dictionary are not supported by XmlSerializer, we avoid the dictionary of generics being serialized, just add xmlignore properties to the field. The code is as follows:
[XmlIgnore]//With XmlIgnore, which indicates serialization does not serialize this property
Dictionary<int Public, payitemtemplate> payitemtemplatedic
48 {
payitemtemplates {return;}
set {payitemtemplates = value;}
51}
OK, so what if we let the generics dictionary not be serialized, and we need to serialize the objects in the generic dictionary to the XML to save them? The idea here is to add an extra payitemtemplate[] array field, The code implementation is as follows:
///<summary>
54///for serialization of Payitemtemplate collections
///</summary>
Payitemtemplates Public payitemtemplate[]
57 {
The Get
59 {
list<payitemtemplate> List = new list<payitemtemplate> (payitemtemplates.count);
Payitemtemplates foreach (keyvaluepair<int,payitemtemplate> pit in)
62 {
The list. ADD (Pit. Value);
64}
65
The return list. ToArray ();
67}
Set
69 {
Payitemtemplates = new Dictionary<int, payitemtemplate> ();
A foreach (Payitemtemplate pit in value)
72 {
Payitemtemplates.add (Pit. Id, Pit);
74}
75}
76}
This is what we need to do, the following tests, specific unit tests, can be viewed in the download source code.
Test results:
Forward Serialization:
<?xml version= "1.0" encoding= "Utf-8"?>
<paytemplate xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd= "Http://www.w3.org/2001/XMLSchema" >
<Id>100</Id>
<Name> Compensation Template Test</name>
<StartDate>2007-08-16T19:10:43.640625+08:00</StartDate>
<PayItemTemplates>
<PayItemTemplate>
<numbericalCategory>Calculational</numbericalCategory>
<NumbericalCategory>Calculational</NumbericalCategory>
<Id>10000</Id>
<Name> Compensation Template Column 1</name>
<PayItemTemplateRelieds>
<PayItemTemplate>
<numbericalCategory>Calculational</numbericalCategory>
<NumbericalCategory>Calculational</NumbericalCategory>
<Id>20000</Id>
<Name> Compensation Template Column 2</name>
<payitemtemplaterelieds/>
<Enabled>true</Enabled>
<Expression>Expression2</Expression>
</PayItemTemplate>
</PayItemTemplateRelieds>
<Enabled>true</Enabled>
<Expression>Expression</Expression>
</PayItemTemplate>
<PayItemTemplate>
<numbericalCategory>Calculational</numbericalCategory>
<NumbericalCategory>Calculational</NumbericalCategory>
<Id>20000</Id>
<Name> Compensation Template Column 2</name>
<payitemtemplaterelieds/>
<Enabled>true</Enabled>
<Expression>Expression2</Expression>
</PayItemTemplate>
</PayItemTemplates>
<WorkFlowCategory>Simple</WorkFlowCategory>
</PayTemplate>
Reverse Serialization:
Scenario 1 Pros and Cons: No additional objects are defined, but extra fields appear (superfluous because this field only appears for serialization).
3. Option 2: Define a dictionary that supports generics
Can the generics dictionary be properly serialized? Yes, redefine a generic serializabledictionary, let it inherit the generics dictionary in. Net and implement the IXmlSerializable interface, the implementation reference in this article is from XML Serializable Generic Dictionary. Two key methods in the IXmlSerializable interface:
///<summary>
26///of anti-serialization
///</summary>
///<param name= "Reader" ></param>
public void ReadXml (XmlReader reader)
30 {
XmlSerializer Keyserializer = new XmlSerializer (typeof (TKey));
XmlSerializer ValueSerializer = new XmlSerializer (typeof (TValue));
-If reader. isemptyelement | | !reader. Read ())
34 {
return;
36}
37
While reader. NodeType!= xmlnodetype.endelement)
39 {
Reader. Readstartelement ("item");
41
The reader. Readstartelement ("key");
TKey key = (TKey) keyserializer.deserialize (reader);
Reader. Readendelement ();
45
Reader. Readstartelement ("value");
TValue value = (TValue) valueserializer.deserialize (reader);
Reader. Readendelement ();
49
Reader. Readendelement ();
The reader. MoveToContent ();
52
this. ADD (key, value);
54}
Reader. Readendelement ();
56}
57
///<summary>
59 Serialization of///
///</summary>
///<param name= "Writer" ></param>
The public void WriteXml (XmlWriter writer)
63 {
XmlSerializer Keyserializer = new XmlSerializer (typeof (TKey));
XmlSerializer ValueSerializer = new XmlSerializer (typeof (TValue));
66
TKey foreach (this. Keys)
68 {
Writer. WriteStartElement ("item");
70
Writer. WriteStartElement ("key");
Keyserializer.serialize (writer, key);
Writer. WriteEndElement ();
74
Writer. WriteStartElement ("value");
Valueserializer.serialize (writer, This[key]);
Writer. WriteEndElement ();
78
Writer. WriteEndElement ();
80}
81}
Complete code check in the source file.
Test results:
Forward Serialization:
<?xml version= "1.0" encoding= "Utf-8"?>
<paytemplatev2 xmlns:xsi= "http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd= "Http://www.w3.org/2001/XMLSchema" >
<Id>100</Id>
<Name> Compensation Template Test</name>
<StartDate>2007-08-16T19:08:45.0625+08:00</StartDate>
<PayItemTemplates>
<item>
<key>
<int>10000</int>
</key>
<value>
<PayItemTemplateV2>
<numberic