很抱歉超长问题我不想遗漏任何代码。
这是加密和序列化的代码......
public class EncryptionSerialiser
{
byte[] key = {1, 2, 3, 4, 5, 6, 7, 8}; // Where to store these keys is the tricky part,
// you may need to obfuscate them or get the user to input a password each time
byte[] iv = {1, 2, 3, 4, 5, 6, 7, 8};
//string path = Application.StartupPath + @"\" + "test.ser";
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
public void EncryptThenSerialise(object obj, string pathandfilename)
{
// Encryption
using (var fs = new FileStream(pathandfilename, FileMode.Create, FileAccess.Write))
using (var cryptoStream = new CryptoStream(fs, des.CreateEncryptor(key, iv), CryptoStreamMode.Write))
{
BinaryFormatter formatter = new BinaryFormatter();
// This is where you serialize the class
try
{
formatter.Serialize(cryptoStream, obj);
}
catch (Exception ex)
{
// MessageBox.Show(ex.ToString());
}
// cryptoStream.Close();
}
}
public T DecryptThenDeSerialise<T>(object obj, string pathandfilename)
{
// Decryption
using (var fs = new FileStream(pathandfilename, FileMode.Open, FileAccess.Read))
using (var cryptoStream = new CryptoStream(fs, des.CreateDecryptor(key, iv), CryptoStreamMode.Read))
{
BinaryFormatter formatter = new BinaryFormatter();
// This is where you deserialize the class
T deserialized = (T) formatter.Deserialize(cryptoStream);
return deserialized;
}
}
我的高级词典班......
[Serializable]
public class HighLevelDictionary : SerializableDictionary<string, LowLevelDictionary>
{
protected HighLevelDictionary(SerializationInfo info, StreamingContext context)
{
int itemCount = info.GetInt32("ItemCount");
for (int i = 0; i < itemCount; i++)
{
KeyValuePair<string, LowLevelDictionary> kvp =
(KeyValuePair<string, LowLevelDictionary>)
info.GetValue(String.Format("Item{0}", i),
typeof(KeyValuePair<string, LowLevelDictionary
this.Add(kvp.Key, kvp.Value);
}
}
public HighLevelDictionary()
{
}
}
My LowlevelDictionary类......
[Serializable]
public class LowLevelDictionary : SerializableDictionary<string, decimal>
{
protected LowLevelDictionary(SerializationInfo info, StreamingContext context)
{
int itemCount = info.GetInt32("ItemCount");
for (int i = 0; i < itemCount; i++)
{
KeyValuePair<string, decimal> kvp =
(KeyValuePair<string, decimal>)
info.GetValue(String.Format("Item{0}", i),
typeof(KeyValuePair<string, decimal>));
this.Add(kvp.Key, kvp.Value);
}
}
public LowLevelDictionary()
{
}
}
我的可序列化SerializableDictionary类...
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Serialization;
[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{0}", i), typeof(KeyValuePair<TKey, TVal>));
this.Add(kvp.Key, kvp.Value);
}
}
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{0}", 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
}
我的测试代码......
EncryptionSerialiser encryptionSerialiser = new EncryptionSerialiser();
GlobalApplicationSettings globalApplicationSettings = new GlobalApplicationSettings();
// CurrentSingleValueOperation.Save();
HighLevelDictionary highLevelDictionary = new HighLevelDictionary();
LowLevelDictionary lowLevelDictionary = new LowLevelDictionary();
lowLevelDictionary.Add("S1", 0.00m);
lowLevelDictionary.Add("S2", 0.00m);
LowLevelDictionary lowLevelDictionary2 = new LowLevelDictionary();
lowLevelDictionary2.Add("S1", 4.00m);
lowLevelDictionary2.Add("S2", 4.00m);
highLevelDictionary.Add("One", lowLevelDictionary);
highLevelDictionary.Add("tWO", lowLevelDictionary2);
encryptionSerialiser.EncryptThenSerialise(highLevelDictionary,
globalApplicationSettings.PriceSetsFullPath + "SVO0.crypt");
HighLevelDictionary extraHighLevelDictionary = new HighLevelDictionary();
extraHighLevelDictionary = encryptionSerialiser.DecryptThenDeSerialise<HighLevelDictionary>(extraHighLevelDictionary,
globalApplicationSettings.PriceSetsFullPath + "SVO0.crypt");
正如你从上面的图片中看到的那样,在反序列化之后,降低级别的字典似乎丢失了(由空值表示,尽管在序列化之前我检查过它似乎很好。
任何想法?
答案 0 :(得分:1)
您正在使用BinaryFormatter
序列化字典,而不是XmlSerializer
,并且为此目的实现了自定义流构造函数和GetObjectData()
方法 - 这显然无效。但是,您的基类Dictionary<TKey, TValue>
已经实现了ISerializable
,因此它已经有了自己的streaming constructor和GetObjectData()
方法。不是试图创建这些方法的自己版本,而是可以使用它们,它们可以工作:
[Serializable]
public class HighLevelDictionary : SerializableDictionary<string, LowLevelDictionary>
{
public HighLevelDictionary()
{
}
protected HighLevelDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }
}
[Serializable]
public class LowLevelDictionary : SerializableDictionary<string, decimal>
{
protected LowLevelDictionary(SerializationInfo info, StreamingContext context) : base(info, context) { }
public LowLevelDictionary()
{
}
}
[Serializable()]
public class SerializableDictionary<TKey, TVal> : Dictionary<TKey, TVal>, IXmlSerializable
{
#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) : base(info, context) { }
#endregion
#region Constants
private const string DictionaryNodeName = "Dictionary";
private const string ItemNodeName = "Item";
private const string KeyNodeName = "Key";
private const string ValueNodeName = "Value";
#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
}
示例fiddle。
话虽如此,BinaryFormatter
不是保存数据的绝佳选择。例如,请参阅What are the deficiencies of the built-in BinaryFormatter based .Net serialization?和Assembly Independent Serialization in .NET。 XmlSerializer
是一个明显的选择,因为您已经实施了IXmlSerializable
。如果您需要二进制格式,可以考虑protobuf-net。