2017-10-09 8 views
3

で失敗し、私は次のXMLファイルがあります。カスタムクラスがでOutOfMemoryException

<MyConfig> 
    <Item a1="Attrib11" a2="Attrib21" a3="Attrib31" /> 
    <Item a1="Attrib12" a2="Attrib22" a3="Attrib32" /> 
</MyConfig> 

を私は次のヘルパーメソッドを使用して、それをロードします。

public static T Load<T>(string path) 
{ 
    XmlSerializer xml = new XmlSerializer(typeof(T)); 

    using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) 
    using (StreamReader sr = new StreamReader(fs)) 
    { 
     return (T)xml.Deserialize(sr); 
    } 
} 

public static void Save<T>(string path, T contents) 
{ 
    XmlSerializer xml = new XmlSerializer(typeof(T)); 

    using (FileStream fs = new FileStream(path, FileMode.CreateNew, FileAccess.Write, FileShare.Read)) 
    using (StreamWriter sw = new StreamWriter(fs)) 
    { 
     xml.Serialize(sw, contents, ns); 
    } 
} 

これはMyConfigです:

public class MyConfig 
{ 
    [XmlElement("Item")] 
    public List<Item> Items { get; set; } 

    public MyConfig() 
    { 
     Items = new List<Item>(); 
    } 
} 

public class Item : IXmlSerializable 
{ 
    [XmlAttribute()] 
    public string Attrib1 { get; set; } 

    [XmlAttribute()] 
    public string Attrib2 { get; set; } 

    [XmlAttribute()] 
    public string Attrib3 { get; set; } 

    public Item(string attrib1, string attrib2, string attrib3) 
    { 
     Attrib1 = attrib1; 
     Attrib2 = attrib2; 
     Attrib3 = attrib3; 
    } 

    public XmlSchema GetSchema() 
    { 
     return null; 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     if (reader.MoveToContent() == XmlNodeType.Element) 
     { 
      Attrib1 = reader.GetAttribute("a1"); 
      Attrib2 = reader.GetAttribute("a2"); 
      Attrib3 = reader.GetAttribute("a3"); 
     } 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     writer.WriteAttributeString("a1", Attrib1); 
     writer.WriteAttributeString("a2", Attrib2); 
     writer.WriteAttributeString("a3", Attrib3); 
    } 
} 

次に、クラスのシリアライズをチェックするために、次のテストベッドコードがあります。

string file = "somePath"; 

MyConfig myConfig = new MyConfig() 
{ 
    Items = new List<Item>() 
    { 
     new Item("Attrib11", "Attrib21", "Attrib31"), 
     new Item("Attrib12", "Attrib22", "Attrib32"), 
    }, 
}; 

Save(file, myConfig); 

MyConfig myConfig2 = Load<MyConfig>(file); 

これは私がこの問題を解決する方法を、LoadでのOutOfMemory例外で失敗? somePathでファイルをチェックしていて、正しく表示されています。あなたは属性読んだ後に次のノードに進めるためにreaderを指示する必要があり

+0

'ReadXml()'では、外側の要素を正しく消費しますか? [IXmlSerializableを実装するための適切な方法?](https://stackoverflow.com/q/279534)とhttps://www.codeproject.com/Articles/43237/How-to-Implement-IXmlSerializable-Correctly – dbc

+0

@dbcを参照してください。関連するすべてのコードをここに入れておいてください。これは私が初めて 'IXmlSerializable'を使用するクラスをやっていることを意味しています。私はそれがあなたが意味するものなら、すべての属性を読みます。 – TheLethalCoder

答えて

2

:あなたはreader.Read()を呼び出さない場合

public void ReadXml(XmlReader reader) 
{ 
    if (reader.MoveToContent() == XmlNodeType.Element) 
    { 
     Attrib1 = reader.GetAttribute("a1"); 
     Attrib2 = reader.GetAttribute("a2"); 
     Attrib3 = reader.GetAttribute("a3"); 
    } 
    // Go to the next node. 
    reader.Read(); 
} 

は、readerは、何度も何度も同じノードを読み込みますしたがって、最終的にOutOfMemoryExceptionが取得されるまで、XmlSerializerItemインスタンスを無制限に作成します。

+0

だから 'reader.Read()'は本質的に 'reader.MoveToNext()'ですか? – TheLethalCoder

+0

@TheLethalCoderおそらく 'reader.MoveToNext()'と同じでしょうが、 'XmlReader'はそのようなメソッドを持っていません。すべての 'reader.MoveToXXX()'メソッドは現在のノード内の 'reader'を動かすだけですが、' reader'を次のノードに進めません。 – haindl

+1

私の意見では、それが実際に何をしているのかはあまり明らかではありません。 – TheLethalCoder

関連する問題