2009-05-13 4 views
1

私のプログラムのDataModelオブジェクトをファイルに保存し、同じオブジェクトグラフを再度読み込むことができます。私はそれをテキストファイルのいくつかの風味にしたいので、私はそれをdiffしてテキストエディタで開くことができます。 XMLはうまくいくでしょうし、.NETにはXMLシリアル化が組み込まれているので、.NETを開始するのに適しているようです。オブジェクトをテキストファイルにシリアル化する:どのAPI /フレームワークですか?

XML直列化のどのような風味を選ぶべきですか?私はSoapFormatterについて知っていますが、現在は廃止されています。XamlWriter(すてきですが、非常に限定されています)、とDataContractSerializer(どちらもまだ分かりません)

私はオープンソースのフレームワークにもオープンしていますが、私はXMLに縛られていません(JavaScriptSerializerも興味深いように見えます)。

シリアライズの枠組みの中での私の一般的な好みのいくつか:

  • 私は本当に新しく追加されたプロパティをシリアル化するために取得するために任意のコード(またはXML設定ファイル)を記述する必要はないはず。私は属性を追加しなければならないことを(慎重に)受け入れることができましたが、私にとってはオーバーヘッドが少ないほどよいでしょう。
  • コンベンションオーバーコンベンションはです。
  • 循環オブジェクトグラフをシリアル化できるもののボーナスポイント。 I 私がしなければならないのなら、これを避けてください。しかし、他人のシリアライゼーションフレームワークの便宜のために、コーディングをもっと難しくするつもりはありません。
  • 私はプライベートフィールドに直接アクセスするのではなく、プロパティ値を保存するものを好みます。
  • 私は、将来の見通しを可能にするものが欲しいです。プロパティや列挙型の名前を変更した場合、古いファイルをトーストする必要はありません。アップグレードパスを定義し、ロード時に値を再マップする(XML構成ファイルのリームを書き込まないことが望ましい)方法が必要です。古いファイルを開くことができる自動回帰テストを作成できます。
  • 私のオブジェクトのイベントを自動的に無視することができれば、私にすべての属性を追加する必要はありません。イベントは決してテキストフォーマットに書き込む意味がありません。
  • Silverlightと本格的な.NETで動作した場合、それは余計なものになります。 (私はこれを短期的に必要とせず、ただ涼しいです。)

提案はありますか?

答えて

1

これは大きな要件のリストです。個人的には、DataContractSerializerがほとんどのニーズを満たすと思います。

1)プロパティを追加することができ、自動的に選択されます(.Net 3があると仮定します)。5 SP1)

2)それはいくつかのバージョン管理をサポート

3を持っている)それは(私が思う)

4)あなたが明示的にあなたが欲しいものを定義することができPreserveObjectReferencesのように、いくつかの機能が欠けいえ、Silverlightで存在しますシリアル化されているので、プライベートフィールドを除外することはできますが、何も指定しなければそれらはインクルードされます。

5)実際には循環オブジェクトグラフを処理していますが、それについて私にはわかりません。

+0

バージョン管理のサポートに関するいくつかの良い情報があります。データ契約バージョン管理http://msdn.microsoft.com/en-us/library/ms731138.aspx、ベストプラクティス:データ契約バージョン管理http://msdn.microsoft.com/en -us/library/ms733832.aspx。 - Joe White 26秒前 –

+0

Silverlightのように* PreserveObjectReferencesをサポートしています(循環オブジェクトグラフの取得方法です)。 –

1

は、XmlSerializerまたはDataContractSerializerを使用してください。私は彼らが救うことができると賭けているし、あなたは何も必要ありません。

+0

XmlSerializerはプライベートフィールドをシリアル化することができないため、XmlSerializerが迷惑をかけることがありました。これは最終的にバイナリシリアル化(http://msdn.microsoft.com/en-us/library/72hyey7b(VS.71).aspx)につながりました。 DataContractSeraializerはこの問題を解決したようです。私はまだそれを試してみました。 –

0

私はSTHを書いた..プロパティがない場合は、このクラスはすべてREAD_WRITEプロパティをシリアル化します

public class TAObjectSerializer 
{ 
    private static void __serializeData(object result, Type propType, XmlWriter wr) 
    { 
     if (result != null) 
     { 
      TypeConverter tc = TypeDescriptor.GetConverter(result); 
      if (tc != null && tc.CanConvertTo(typeof(string)) && tc.CanConvertFrom(typeof(string))) 
      { 
       wr.WriteString(tc.ConvertTo(result, typeof(string)) as string); 
      } 
      else if (propType.IsArray) 
      { 
       Array tmp = result as Array; 
       if (propType.GetElementType() == typeof(object)) 
       { 
        for (int i = 0; i < tmp.Length; i++) 
        { 
         object v = tmp.GetValue(i); 
         wr.WriteStartElement("item"); 
         if (v == null) 
         { 
          wr.WriteAttributeString("type", ""); 
         } 
         else 
         { 
          Type vt = v.GetType(); 
          wr.WriteAttributeString("type", (vt.IsPrimitive || v is string || v is decimal || v is DateTime || vt.IsArray) ? vt.ToString() : vt.AssemblyQualifiedName); 
          __serializeData(v, v.GetType(), wr); 
         } 
         wr.WriteEndElement(); 
        } 
       } 
       else 
       { 
        for (int i = 0; i < tmp.Length; i++) 
        { 
         object v = tmp.GetValue(i); 
         wr.WriteStartElement("item"); 
         if (v != null) 
         { 
          __serializeData(v, v.GetType(), wr); 
         } 
         wr.WriteEndElement(); 
        } 
       } 
      } 
      else if (propType.IsSerializable) 
      { 
       using (MemoryStream __ = new MemoryStream()) 
       { 
        BinaryFormatter bf = new BinaryFormatter(); 
        bf.Serialize(__, result); 
        wr.WriteString(Convert.ToBase64String(__.ToArray())); 
       } 
      } 
      else if (propType.IsClass) 
      { 
       wr.WriteRaw(__serialize(result)); 
      } 
     } 
    } 
    private static void __serializeItem(object obj, PropertyInfo pi, XmlWriter wr) 
    { 
     Type propType = pi.PropertyType; 
     object result = pi.GetValue(obj, null); 
     wr.WriteStartElement("property"); 
     wr.WriteAttributeString("type", (propType.IsPrimitive || result is string || result is decimal || result is DateTime || propType.IsArray) ? propType.ToString() : propType.AssemblyQualifiedName); 
     wr.WriteAttributeString("name", pi.Name); 
     __serializeData(result, propType, wr); 
     wr.WriteEndElement(); 
    } 
    private static string __serialize(object obj) 
    { 
     StringBuilder sb = new StringBuilder(); 
     XmlWriterSettings set = new XmlWriterSettings(); 
     set.OmitXmlDeclaration = true; 
     using (XmlWriter wr = XmlWriter.Create(sb, set)) 
     { 
      Type t = obj.GetType(); 
      wr.WriteStartElement("object"); 
      wr.WriteAttributeString("type", t.AssemblyQualifiedName); 
      if (t.IsClass && !(obj is string)) 
      { 
       PropertyInfo[] list = t.GetProperties(); 
       foreach (PropertyInfo pi in list) 
       { 
        if (pi.CanRead && pi.CanWrite && pi.GetCustomAttributes(typeof(NonSerializedAttribute), true).Length == 0) 
        { 
         __serializeItem(obj, pi, wr); 
        } 
       } 
      } 
      wr.WriteEndElement(); 
     } 
     return sb.ToString(); 
    } 
    public static XmlDocument Serialize(object obj) 
    { 
     if (obj == null) 
      throw new ArgumentNullException("obj"); 
     XmlDocument doc = new XmlDocument(); 
     string str = __serialize(obj); 
     if (!string.IsNullOrEmpty(str)) 
      doc.LoadXml(str); 
     return doc; 
    } 
    private static object __deserializeItem(Type propType, XmlNode node) 
    { 
     TypeConverter tc = TypeDescriptor.GetConverter(propType); 
     if (tc != null && tc.CanConvertTo(typeof(string)) && tc.CanConvertFrom(typeof(string))) 
     { 
      return tc.ConvertFrom(node.InnerText); 
     } 
     else if (propType.IsArray) 
     { 
      if (propType.GetElementType() == typeof(object)) 
      { 
       XmlNodeList nl = node.SelectNodes("item"); 
       Array tmp = Array.CreateInstance(typeof(object), nl.Count); 
       for (int i = 0; i < nl.Count; i++) 
       { 
        XmlNode p = nl[i]; 
        Type _t = Type.GetType(p.Attributes["type"].Value); 
        if (_t == null) 
         tmp.SetValue(null, i); 
        else 
         tmp.SetValue(__deserializeItem(_t, p), i); 
       } 
       return tmp; 
      } 
      else 
      { 
       Type _t = propType.GetElementType(); 
       XmlNodeList nl = node.SelectNodes("item"); 
       Array tmp = Array.CreateInstance(_t, nl.Count); 
       for (int i = 0; i < nl.Count; i++) 
       { 
        XmlNode p = nl[i]; 
        tmp.SetValue(__deserializeItem(_t, p), i); 
       } 
       return tmp; 
      } 
     } 
     else if (propType.IsSerializable) 
     { 
      using (MemoryStream __ = new MemoryStream(Convert.FromBase64String(node.InnerText))) 
      { 
       BinaryFormatter bf = new BinaryFormatter(); 
       return bf.Deserialize(__); 
      } 
     } 
     else if (propType.IsClass) 
     { 
      return __deserialize(node); 
     } 
     return null; 
    } 
    private static object __deserialize(XmlNode t) 
    { 
     try 
     { 
      object tmp = Activator.CreateInstance(Type.GetType(t.Attributes["type"].Value)); 
      XmlNodeList nl = t.SelectNodes("property"); 
      Type objType = tmp.GetType(); 
      foreach (XmlNode p in nl) 
      { 
       string name = p.Attributes["name"].Value; 
       PropertyInfo pi = objType.GetProperty(name); 
       Type propType = Type.GetType(p.Attributes["type"].Value); 
       if (propType == pi.PropertyType) 
       { 
        pi.SetValue(tmp, __deserializeItem(propType, p), null); 
       } 
      } 
      return tmp; 
     } 
     catch 
     { 
     } 
     return null; 
    } 
    public static object Deserialize(XmlDocument doc) 
    { 
     XmlNode nd = doc.SelectSingleNode("object"); 
     if (nd == null) 
      throw new ArgumentOutOfRangeException(); 
     return __deserialize(nd); 
    } 
} 

**

Usage : 
Serialize : TAObjectSerializer.Serialize(myClassInstance); //this returns as XmlDocument 
Deserialize : TAObjectSerializer.Deserialize(myXmlDocument); //this returns as object instance 

**

.. uのを助けるために願っています非シリアル化属性属性

幸運を祈る!

+0

これは双方向リンクをサポートする方法はありますか? – Pygmy

関連する問題