sharplib/ser/SerializableDictionary.cs
2021-06-17 01:48:02 -07:00

166 lines
4.3 KiB
C#

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;
using System.Xml;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Security.Permissions;
namespace lib
{
[Serializable]
public class SerializableDictionary<TKey, TVal>: Dictionary<TKey, TVal>, IXmlSerializable, ISerializable
{
#region Constants
private const string DictionaryNodeName = "Dictionary";
private const string ItemNodeName = "Item";
private const string KeyNodeName = "Key";
private const string ValueNodeName = "Value";
#endregion
#region Constructors
public SerializableDictionary()
{
}
public SerializableDictionary( IDictionary<TKey, TVal> dictionary )
: base( dictionary )
{
}
public SerializableDictionary( IEqualityComparer<TKey> comparer )
: base( comparer )
{
}
public SerializableDictionary( int capacity )
: base( capacity )
{
}
public SerializableDictionary( IDictionary<TKey, TVal> dictionary, IEqualityComparer<TKey> comparer )
: base( dictionary, comparer )
{
}
public SerializableDictionary( int capacity, IEqualityComparer<TKey> comparer )
: base( capacity, comparer )
{
}
#endregion
#region ISerializable Members
protected SerializableDictionary( SerializationInfo info, StreamingContext context )
{
int itemCount = info.GetInt32("ItemCount");
for( int i = 0; i < itemCount; i++ )
{
KeyValuePair<TKey, TVal> kvp = (KeyValuePair<TKey, TVal>)info.GetValue(String.Format( $"Item{i}" ), typeof(KeyValuePair<TKey, TVal>));
this.Add( kvp.Key, kvp.Value );
}
}
[SecurityPermission( SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter )]
void ISerializable.GetObjectData( SerializationInfo info, StreamingContext context )
{
info.AddValue( "ItemCount", this.Count );
int itemIdx = 0;
foreach( KeyValuePair<TKey, TVal> kvp in this )
{
info.AddValue( String.Format( $"Item{itemIdx}" ), kvp, typeof( KeyValuePair<TKey, TVal> ) );
itemIdx++;
}
}
#endregion
#region IXmlSerializable Members
void IXmlSerializable.WriteXml( System.Xml.XmlWriter writer )
{
//writer.WriteStartElement(DictionaryNodeName);
foreach( KeyValuePair<TKey, TVal> kvp in this )
{
writer.WriteStartElement( ItemNodeName );
writer.WriteStartElement( KeyNodeName );
KeySerializer.Serialize( writer, kvp.Key );
writer.WriteEndElement();
writer.WriteStartElement( ValueNodeName );
ValueSerializer.Serialize( writer, kvp.Value );
writer.WriteEndElement();
writer.WriteEndElement();
}
//writer.WriteEndElement();
}
void IXmlSerializable.ReadXml( System.Xml.XmlReader reader )
{
if( reader.IsEmptyElement )
{
return;
}
// Move past container
if( !reader.Read() )
{
throw new XmlException( "Error in Deserialization of Dictionary" );
}
//reader.ReadStartElement(DictionaryNodeName);
while( reader.NodeType != XmlNodeType.EndElement )
{
reader.ReadStartElement( ItemNodeName );
reader.ReadStartElement( KeyNodeName );
TKey key = (TKey)KeySerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadStartElement( ValueNodeName );
TVal value = (TVal)ValueSerializer.Deserialize(reader);
reader.ReadEndElement();
reader.ReadEndElement();
this.Add( key, value );
reader.MoveToContent();
}
//reader.ReadEndElement();
reader.ReadEndElement(); // Read End Element to close Read of containing node
}
System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema()
{
return null;
}
#endregion
#region Private Properties
protected XmlSerializer ValueSerializer
{
get
{
if( valueSerializer == null )
{
valueSerializer = new XmlSerializer( typeof( TVal ) );
}
return valueSerializer;
}
}
private XmlSerializer KeySerializer
{
get
{
if( keySerializer == null )
{
keySerializer = new XmlSerializer( typeof( TKey ) );
}
return keySerializer;
}
}
#endregion
#region Private Members
private XmlSerializer keySerializer = null;
private XmlSerializer valueSerializer = null;
#endregion
}
}