web-dev-qa-db-ja.com

他のクラスのオブジェクトを含むクラスをシリアル化する方法(再帰的シリアル化?)

これどうやってするの?または、シリアライザーは自動的に再帰を実行し、それらすべての子オブジェクトをXMLにシリアル化しますか?

他のクラスのオブジェクトを含むクラスをシリアル化する方法の例を教えてください!それがこの質問の核心でした!

これを試しましたが、ターゲットのXMLファイルにanything(XMLヘッダーを除く)が出力されませんでした。

私の問題は、Listオブジェクトを保持するだけの単純なクラスをシリアル化する必要があることです。ただし、これらのエンティティはListオブジェクトも保持します。 (もう1つの利点は、一部のコンポーネントが派生していて辞書が含まれているため、一部のコンポーネントのシリアル化を回避できる場合です)。

_public void SaveCurrent(string MapFileName)
{
    string MapPath = world_.game_.Content.RootDirectory + "/Maps/" + MapFileName + ".xml";
    StreamWriter MapWriter = new StreamWriter(MapPath);

    Map SavedMap = new Map();
    SavedMap.Entities = world_.Entities;
    XmlSerializer xSerializer = new XmlSerializer(SavedMap.GetType());

    xSerializer.Serialize(MapWriter, SavedMap);
    MapWriter.Close();
}
_

これが、シリアル化を行うコードです。

_public class Map
{
    internal string MapName;
    internal string MapDescription;
    internal string MapAuthor;
    public List<Entity> Entities = new List<Entity>();
}
_

そして、これはシリアル化されたクラスです。 シリアル化が同じアセンブリから呼び出された場合、内部はパブリックとしてカウントできますか? コードはSavedMap.GetType()関数で例外をスローし、私もtypeof(Map)を試しましたが、成功しませんでした。新しいクラスを処理する他の方法(ディープシリアル化)が必要なためだと思います。どうすればよいですか?

また、いくつかの例で、インターフェイスの継承や属性がないことがわかったので、それらも追加しませんでしたが、WriteXML内で別のシリアル化を呼び出す方法がわかりませんが、IXmlSerializableを使用する予定です。実装。

15
Johnny

Josh Einsteinが言及した型の問題については、XmlInclude属性を操作する必要はありません。型のリストをシリアライザーに渡すこともできます(署名はXmlSerializer(Type baseType, Type[] extraTypes)です)。これは、追加のタイプリストが時間の経過とともに大きくなる可能性がある場合は特に実行する必要があります。

エクストラタイプの検索は、シリアル化するオブジェクトをリフレクションするか、ロードされたアセンブリを起動時にリフレクションして必要なタイプをフェッチすることで実行できます。

編集:生の例:

public abstract class Animal
{
}

public class Dog : Animal
{
}

public class Cat : Animal
{
}

public static class AnimalSerializer
{
    public static void Serialize(List<Animal> animals, Stream stream)
    {
        List<Type> animalTypes = new List<Type>();
        foreach (Animal animal in animals)
        {
            Type type = animal.GetType();
            if (!animalTypes.Contains(type))
            {
                animalTypes.Add(type);
            }
        }
        XmlSerializer serializer = new XmlSerializer(typeof(List<Animal>), animalTypes.ToArray());
        serializer.Serialize(stream, animals);
    }
}
2
Sylvestre Equy

SerializableとXmlを追加するクラスを含める:

[System.Serializable]
[System.Xml.Serialization.XmlInclude(typeof(Entity))]
public class Map
{
    internal string MapName;
    internal string MapDescription;
    internal string MapAuthor;
    public List<Entity> Entities = new List<Entity>();
}

使用法:

System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(Map));
serializer.Serialize(mapWriter, savedMap);
6
pr0gg3r

グラフ内のすべてのオブジェクトがシリアル化可能である限り、オブジェクトグラフ全体(オブジェクトと、パブリックメンバーを介して公開されるオブジェクトを再帰的に)をシリアル化します。シリアライザーが異なれば、シリアライズ可能なものについてのルールも異なります。たとえば、XmlSerializerにはデフォルトのパブリックコンストラクタが必要です。

また、XMLシリアライザーは、タイプ情報とそれらのタイプの属性のみに基づいて、シリアル化するタイプの種類を判別できる必要があります。たとえば、Animalタイプのプロパティを持つクラスがあるが、実行時にXmlSerializerがDogタイプのオブジェクトをそこに見つけたとします。これをサポートするには、 XmlInclude 属性を使用して、Dogをサポートする必要があることを事前に通知する必要があります。

オブジェクトグラフの一部をシリアル化された出力から除外するには、 XmlIgnore 属性を使用します。シリアライザーが異なれば、含める/無視するなどの属性も異なります。

これが少し明確にするのに役立つことを願っています。 MSDNのこのトピック についても読むことをお勧めします。

3
Josh

どのくらいの制御が必要ですか?いつでもIXmlSerializableを実装できます-

http://msdn.Microsoft.com/en-us/library/system.xml.serialization.ixmlserializable.aspx

2
Kris Krause