2016-08-23 2 views
0

すごく長い質問のため申し訳ありません、私はコードを残したくありませんでした。これは、暗号化とシリアル化するコードです私のクラスは正しくシリアル化されませんでした

...

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; 
     } 
    } 

マイハイレベルDictionaryクラス...

[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() 
    {   
    } 
} 

マイ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"); 

Issue

あなたは上の画像から見ることができるように低いレベルの辞書のものは、逆シリアル化後に失われたようです(連載の前にも、NULL値で示されます私はチェックし、それはうまくいくようだ。

+0

[SerializableDictionary <>](http://stackoverflow.com/a/3672070/1997232)。 – Sinatr

+2

HighLevelDictionaryのコンストラクタはprivateです。公開してみてください。 – jdweng

+0

あなたの提案をお寄せいただきありがとうございます。それは保護されていないプライベートではありません。 – user3755946

答えて

1

xmlのシリアル化では実装が正常に機能しますが、の場合はEncryptionSerialiserクラスでは使用できません。これはここで重要な情報です。

SerializableDictionaryベースクラスのシリアル化の実装は、IXmlSerializableインターフェイスの実装に基づいています。 This interfaceXmlSerializerによって呼び出されますが、バイナリのシリアル化では使用されません。私は、より高いレベルDictionarySerializable属性のためにデフォルトでシリアル化されていると思います。

バイナリアプローチに適したインターフェイスを実装する必要があります。どうやら作業されていない - 私はあなたがいないXmlSerializer、あなたの辞書をシリアライズするBinaryFormatterを使用しており、この目的のためにカスタムのストリーミングコンストラクタとGetObjectData()メソッドを実装しているthis

1

で始まります。ただし、基底クラスDictionary<TKey, TValue>は既にに実装されていますので、すでに独自のstreaming constructorGetObjectData()メソッドを実装しています。むしろこれらのメソッドの独自のバージョンを作成しようとするよりも、あなただけそれらを使用することができ、彼らは動作します:

[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を参照してください。 IXmlSerializableを既に実装しているため、XmlSerializerは明らかな代替手段の1つです。バイナリ形式が必要な場合は、と考えることができます。

関連する問題