1

FooContainer(リスト)を逆シリアル化しようとすると、エラーがスローされます。このコードの最後の部分を見てください。

public interface IFoo
{
    object Value { get; }
}

public abstract class Foo<T> : IFoo
{
    [XmlElement("Value")]
    public T Value { get; set; }
    [XmlIgnore]
    object IFoo.Value { get { return Value; } }
}

public class FooA : Foo<string> { }
public class FooB : Foo<int> { }
public class FooC : Foo<List<Double>> { }

[XmlRoot("Foos")]
public class FooContainer : List<IFoo>, IXmlSerializable
{
    public XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(XmlReader reader)
    {
        XmlSerializer serial = new XmlSerializer(typeof(FooContainer));
        serial.Deserialize(reader);
    }

    public void WriteXml(XmlWriter writer)
    {
        ForEach(x =>
            {
                XmlSerializer serial = new XmlSerializer(x.GetType(),
            new Type[] { typeof(FooA), typeof(FooB), typeof(FooC) });
                serial.Serialize(writer, x);
            });
    }
}

class Program
{
    static void Main(string[] args)
    {
        FooContainer fooList = new FooContainer()
        {
            new FooA() { Value = "String" },
            new FooB() { Value = 2 },
            new FooC() { Value = new List<double>() {2, 3.4 } } 
        };

        XmlSerializer serializer = new XmlSerializer(fooList.GetType(),
            new Type[] { typeof(FooA), typeof(FooB), typeof(FooC) });
        System.IO.TextWriter textWriter = new System.IO.StreamWriter(@"C:\temp\movie.xml");
        serializer.Serialize(textWriter, fooList);
        textWriter.Close();

        XmlReader reader = XmlReader.Create(@"C:\temp\movie.xml");
        var a = serializer.Deserialize(reader);
    }
}

私は何が間違っているのですか?

4

3 に答える 3

3

私はまったく同じ問題を抱えていました:

私にはset、インターフェースIFooまたはクラスが欠落しているように見えますFoo。オブジェクトがないsetと読み取り専用になり、StackOverflowExceptionXMLをオブジェクトに逆シリアル化しようとするとが表示されます。

属性を追加setするだけで、問題は解決しました。

于 2012-09-27T11:22:00.867 に答える
2

あなたは何のためにあるのか理解していないようですIXmlSerializable。これは、のデフォルトの動作をオーバーライドXmlSerializerするためのものです。別のスピンアップして/メソッドXmlSerializerで実際にシリアル化/逆シリアル化する場合は、そうです。そのシリアライザーは、まったく同じオブジェクトから取得したまったく同じ//メソッドを呼び出すためです。WriteXmlReadXmlStackOverflowExceptionWriteXmlReadXml

IXmlSerializableそれは実際には何もしないので、その実装を取り除くだけです。または、このCPの記事を読んでください。

IXmlSerializableを正しく実装する方法

基本的に、オブジェクトの読み取りまたは書き込みには、標準Read*Write*メソッドを使用することになっています。XmlReaderXmlWriter

内部またはメソッドを使用することは必ずしも間違っているとは限りません。オブジェクトグラフの宣言型のインスタンスと等しくない、または含まれていない別のオブジェクトをシリアル化/逆シリアル化するために使用している限りです。XmlSerializerReadXmlWriteXml

于 2012-05-04T01:22:35.810 に答える
0

ReadXml念のためデバッグしますが、の実装は再帰的 だと思います。ReadXml呼び出しDeserialize、呼び出しReadXml、呼び出しDeserialize、など。

ReadXmlthis渡されたリーダーを使用してxmlを読み取り、Xmlデータに基づいてオブジェクト(つまり)をハイドレイトする必要があります。

MSDNから

ReadXmlメソッドは、WriteXmlメソッドによって書き込まれた情報を使用してオブジェクトを再構成する必要があります。

このメソッドが呼び出されると、リーダーは、タイプの情報をラップする要素の先頭に配置されます。つまり、シリアル化されたオブジェクトの開始を示す開始タグの直前です。このメソッドが戻るとき、そのすべての内容を含めて、要素全体を最初から最後まで読み取っていなければなりません。WriteXmlメソッドとは異なり、フレームワークはラッパー要素を自動的に処理しません。実装はそうしなければなりません。これらのポジショニングルールに従わないと、コードで予期しないランタイム例外が生成されたり、データが破損したりする可能性があります。

このメソッドを実装するときは、悪意のあるユーザーが、アプリケーションの動作を無効にするか変更するために、整形式であるが無効なXML表現を提供する可能性を考慮する必要があります。

于 2012-05-04T01:13:16.973 に答える