2009-05-20 8 views
5

deserializing नहीं है मैं सी # XmlSerializer के लिए नया हूँ तो मुझे यहां कुछ बुनियादी याद आ रही है।XmlSerializer.Deserialize() एक सूची <T> सही ढंग से

जिस समस्या में मैं दौड़ रहा हूं वह यह है कि मेरे पास एक वर्ग है जिसमें List<T> किसी अन्य वर्ग का है। जब मैं मुख्य वर्ग को क्रमबद्ध करता हूं तो एक्सएमएल सुंदर दिखता है और सभी डेटा बरकरार है। जब मैं एक्सएमएल को deserialize, List<T> में डेटा गायब हो जाता है और मुझे खाली List<T> के साथ छोड़ दिया गया है। मुझे कोई त्रुटि नहीं मिल रही है और धारावाहिक भाग आकर्षण की तरह काम करता है।

मुझे deserialization प्रक्रिया के साथ क्या याद आ रही है?

संपादित करें: ध्यान दें कि नीचे दिखाया गया कोड समस्या को पुन: उत्पन्न नहीं करता है - यह काम करता है। यह वास्तविक कोड का सरलीकृत संस्करण था, जिसने काम नहीं किया था। दुर्भाग्यवश, नीचे दिया गया कोड समस्या को पुन: उत्पन्न करने के लिए पर्याप्त सरलीकृत नहीं था!

public class User 
{ 
    public User() 
    { 
    this.Characters = new List<Character>(); 
    } 
    public string Username { get; set; } 
    public List<Character> Characters { get; set; } 
} 

public class Character 
{ 
    public Character() 
    { 
    this.Skills = new List<Skill>(); 
    } 
    public string Name { get; set; } 
    public List<Skill> Skills { get; set; } 
} 

public enum Skill 
{ 
    TreeClimber, 
    ForkliftOperator 
} 

public static void Save(User user) 
{ 
    using (var textWriter = new StreamWriter("data.xml")) 
    { 
     var xmlSerializer = new XmlSerializer(typeof(User)); 
     xmlSerializer.Serialize(textWriter, user); 
    } 
} 

public static User Restore() 
{ 
    if (!File.Exists("data.xml")) 
     throw new FileNotFoundException("data.xml"); 

    using (var textReader = new StreamReader("data.xml")) 
    { 
     var xmlSerializer = new XmlSerializer(typeof(User)); 
     return (User)xmlSerializer.Deserialize(textReader); 
    } 
} 

public void CreateAndSave() 
{ 
    var character = new Character(); 
    character.Name = "Tranzor Z"; 
    character.Skills.Add(Skill.TreeClimber); 

    var user = new User(); 
    user.Username = "Somebody"; 
    user.Characters.Add(character); 

    Save(user); 
} 

public void RestoreAndPrint() 
{ 
    var user = Restore(); 
    Console.WriteLine("Username: {0}", user.Username); 
    Console.WriteLine("Characters: {0}", user.Characters.Count); 
} 

एक्सएमएल CreateAndSave (क्रियान्वित द्वारा उत्पन्न) तो दिखाई देता है:

<User> 
    <Username>Somebody</Username> 
    <Characters> 
    <Character> 
     <Name>Tranzor Z</Name> 
     <Skills> 
     <Skill>TreeClimber</Skill> 
     </Skills> 
    </Character> 
    <Characters> 
</User> 

बिल्कुल सही! जिस तरह से इसे देखना चाहिए। मैं तो RestoreAndPrint() निष्पादित अगर मैं प्रयोक्ता नाम संपत्ति के साथ एक उपयोगकर्ता वस्तु ठीक से सेट मिलता है लेकिन वर्ण संपत्ति एक खाली सूची है:

Username: Somebody 
Characters: 0 

किसी को क्यों वर्ण संपत्ति ठीक से धारावाहिक है मेरे लिए व्याख्या कर सकते हैं लेकिन deserialize नहीं होगा?

+3

आपको प्रकारों पर [Serializable] की आवश्यकता नहीं है। एक्सएमएल सीरिएलाइज़र का व्यवहार उस विशेषता से पूरी तरह से स्वतंत्र है। – Cheeso

+0

ठीक है; इसलिए जब से हम (या मुझे, कम से कम) संदेह है कि समस्या "असली" कोड में है (दिखाया नहीं गया है); क्या आप सूचियों के "सेट" एक्सेसर में कुछ भी दिलचस्प करते हैं? यह पहला स्थान होगा जो मैं देखता हूं। –

+0

नहीं, वे सभी बुनियादी गुण हैं जिनके पास प्राप्त या सेट एक्सेसर्स में कुछ भी नहीं है। वे सब थोड़े दिखते हैं: सार्वजनिक टी संपत्ति नाम {प्राप्त करें; सेट; } – Andy

उत्तर

1

एक लंबे समय के लिए कोड के साथ आसपास futzing बाद मैं अंत में XmlSerializer के डिफ़ॉल्ट व्यवहार का उपयोग कर के विचार पर छोड़ दिया।

सभी प्रासंगिक कक्षाएं अब IXmlSerializer का उत्तराधिकारी हैं और ReadXml() और WriteXml() फ़ंक्शंस को लागू करती हैं। मैं वास्तव में आलसी मार्ग लेने की उम्मीद कर रहा था लेकिन अब जब मैंने IXmlSerializer के साथ खेला है, मुझे एहसास है कि यह वास्तव में मुश्किल नहीं है और अतिरिक्त लचीलापन वास्तव में अच्छा है।

[System.Xml.Serialization.XmlElementAttribute("NameOfMyField")] 
public List<SomeType> NameOfMyField{get;set;} 

मुझे लगता है कि यह आपके समाधान है:

-2

इसे enum के deserializing के साथ करना पड़ सकता है .... क्योंकि यह इसे स्ट्रिंग मान के रूप में serialized ... चरित्र के लिए सही enum मूल्य बनाने में परेशानी हो सकती है। इस परिकल्पना का परीक्षण नहीं किया है ...

+0

मेरे वास्तविक कोड प्रोजेक्ट में रूट क्लास में अन्य enums हैं जो क्रमबद्ध और deserialized ठीक से किया जा रहा है। मैं वर्ण सूची में सफलतापूर्वक व्यक्तिगत वस्तुओं को क्रमबद्ध और deserialize कर सकते हैं। यह केवल तब होता है जब उपयोगकर्ता ऑब्जेक्ट को deserializing है कि प्रक्रिया टूट जाती है और वर्ण सूची खाली है और कोई अपवाद नहीं फेंक दिया जा रहा है। – Andy

+0

-1: enum के साथ कोई समस्या नहीं है। मैं भविष्य में या तो परीक्षण में सिफारिश करता हूं, या कुछ भी नहीं कहूंगा। –

0
Stream stream = File.Open(filename + ".xml", FileMode.Open); 
User user = null; 
using (XmlReader reader = XmlReader.Create(stream)) 
{ 
    user = IntermediateSerializer.Deserialize<User>(reader, null); 
} 
stream.Close(); 

return user; 

मैं इस तरह कुछ उपयोग करने का प्रयास करूंगा।

+0

मैं जिस कोड के साथ काम कर रहा हूं * है * गेम से संबंधित है लेकिन मैं इस परियोजना में एक्सएनए फ्रेमवर्क का संदर्भ नहीं दे रहा हूं, इसलिए मुझे इंटरमीडिएट सेराइलाइज़र तक कोई पहुंच नहीं है। – Andy

+0

क्षमा करें, मैंने धारणा बनाई है। –

5

पुन: पेश नहीं कर सकता; मैं (और तत्काल बगों के बाद) मिलती है:

Username: Somebody 
Characters: 1 

परिवर्तन:

  • बजाय WriteLineWriteFormat (जो यह संकलन रोका गया)
  • डिफ़ॉल्ट कंस्ट्रक्टर्स में सूची (जो CreateAndSave रोका init काम करने से):
    • public User() { Characters = new List<Character>(); }
    • public Character() { Skills = new List<Skill>(); }
+1

एचआरएम ... मैंने जो कोड ऊपर पोस्ट किया था वह नमूना कोड था जो मेरे असली कोड की नकल करता था, इसलिए मेरी गलतियों, माफ करना '। मेरी वास्तविक परियोजना काफी बड़ी है लेकिन पोस्ट किया गया कोड एक बहुत करीबी अनुमान है जो मैं करने की कोशिश कर रहा हूं। मेरा इरादा एक उदाहरण प्रदान करना था जो सभी गौरी विवरण प्रदान किए बिना मेरी स्थिति का प्रतिनिधित्व करता है। :/ – Andy

+0

दुर्भाग्यवश, मुझे लगता है कि समस्या उस कोड में है जो छोड़ी गई है। –

+0

हे।मैं एक प्रोटोबफ-नेट देखता हूं लेकिन इस परियोजना के लिए मेरा लक्ष्य एक मानव पठनीय/संपादन योग्य प्रारूप था जिसे किसी भी मूल पाठ संपादक के साथ छेड़छाड़ की जा सकती थी। – Andy

2

अतीत में, जब सूचियों serializing, मैं [XmlArray] और [XmlArrayItem] एनोटेशन का उपयोग किया है। फिर आप अक्षरों की संपत्ति पर एक [XmlIgnore] एनोटेशन डाल देंगे। आपके मामले में, यह कुछ ऐसा दिखाई देगा:

[XmlArray("Characters")] 
[XmlArrayItem("Character", Type=typeof(Character))] 
public Character[] _ Characters 
{ 
    get 
    { 
     //Make an array of Characters to return 
     return Characters.ToArray(); 
    } 

    set 
    { 
     Characters.Clear(); 
     for(int i = 0; i < value.Length; i++) 
      Characters.Add(value[i]); 
    } 
} 

आशा है कि मदद करता है।

+0

कोई भाग्य नहीं - मुझे एक ही परिणाम मिल रहा है, यानी एक खाली सूची। जब मैं deserialize, चरित्र से संबंधित कोड को छुआ नहीं जा रहा है। ऐसा लगता है कि एक्सएमएल में पूरे वर्ण नोड को संसाधित किए बिना फेंक दिया जा रहा है। – Andy

1

शायद, StreamReader के बजाय, इसके बजाय XmlReader बनाएं। साथ ही, एक समस्या निवारण चरण के रूप में, आप "var" घोषणाओं के बजाय अपने मौजूदा कोड को स्पष्ट प्रकार (नीचे के रूप में) के साथ आज़मा सकते हैं।

public static User Restore() 
{ 
    if (!File.Exists("data.xml")) 
    throw new FileNotFoundException("data.xml"); 

    XmlReader xr = XmlReader.Create("data.xml"); 
    XmlSerializer serializer = new XmlSerializer(typeof(User)); 
    var user = (User)serializer.Deserialize(xr); 
    xr.Close(); 
    return user; 
} 

संपादित करें: इसके अलावा, आपके उपयोगकर्ता वर्ग पर XmlInclude एनोटेशन का प्रयास करें।

[XmlInclude(typeof(Character))] 
+0

मैंने XmlIncludeAttributes को सभी प्रासंगिक वर्गों में जोड़ा और deserialization अभी भी विफल रहा। – Andy

0

मैं अपने सूची प्रकार को यह विशेषता को जोड़ कर यह तो काम (अपने एक ही समस्या थी)।

1

मुझे पता है कि यह पुराना है लेकिन मुझे एक ही समस्या है।

मुझे जो मिला वह यह है कि यदि मेरे पास एक ऑब्जेक्ट है जो ग्राफ़ में IXmlSerializable लागू करता है (इसलिए मुख्य ऑब्जेक्ट जिसे मैं इंटरफेस को कार्यान्वित नहीं करना चाहता हूं, लेकिन इसमें एक ऑब्जेक्ट इसे लागू करता है), यह सभी को खंडित करता है अक्रमांकन। सूची अब और निराशाजनक नहीं है, न ही वस्तु जिसके बारे में मैं बात कर रहा हूं। सीरियलाइजेशन सही काम करता है।

+3

पता चला क्यों: ReadXml में पाठक को समापन टैग पर अग्रिम करने की देखभाल करें। –

+1

एक बहुत अच्छा अवलोकन करता है जो महत्वपूर्ण है यदि आपने IXmlSerializable लागू किया है - सुनिश्चित करें कि आप पाठक के साथ समाप्त करें। ReadEndElement(); अपने कस्टम एक्सएमएल रीडर तर्क के अंत में –

+0

इच्छा है कि मैं आपको दस बार दोनों को ऊपर उठा सकता हूं ... क्यों पृथ्वी पर एमएसडीएन आलेख मैंने वर्बैटिम से कोड की प्रतिलिपि बनाई है, क्या यह त्रुटि है? – vines

संबंधित मुद्दे