2013-02-13 16 views
7

मेरे पास एक ऑब्जेक्ट है जिसे मैं एक्सएमएल में क्रमबद्ध करने की कोशिश कर रहा हूं। इस वस्तु के अंदर एक सामान्य प्रकार (सार वर्ग) की एक सूची है। इस सूची का प्रत्येक आइटम एक अलग वर्ग हो सकता है, लेकिन सभी सार आधार वर्ग से इनहेरिट कर रहे हैं:एक ही प्रकार के नाम के साथ एक पॉलिमॉर्फिक सूची को क्रमबद्ध करें

<animal type="cat"> 
    <size>medium</size> 
    <furColor>black</furColor> 
</animal> 
<animal type="fish"> 
    <size>small</size> 
    <scaleColor>silver</scaleColor> 
</animal> 

मैं:

public abstract class animal 
{ 
    public string type { get; set; } 
} 
public class cat:animal 
{ 
    public string size { get; set; } 
    public string furColor { get; set; } 
} 
public class fish:animal 
{ 
    public string size { get; set; } 
    public string scaleColor { get; set; } 
} 

जब मैं सूची को क्रमानुसार, मैं इसे इस तरह दिखना चाहते हैं मैंने सरल समाधान की कोशिश की है:

[XmlElement("Animal")] 
public List<animal> Animals { get; set; } 

लेकिन यह एक त्रुटि फेंकता है क्योंकि यह ऑब्जेक्ट प्रकार "बिल्ली" की अपेक्षा नहीं कर रहा है। [XmlInclude] टैग को बेस क्लास, व्युत्पन्न कक्षा, या पूरी युक्त कक्षा में जोड़ें (चलो इसे चिड़ियाघर कहते हैं) इससे मदद नहीं करता है।

मैं एक ही वर्ग के लिए typeof पदनाम का उपयोग कर सकते हैं:

[XmlElement("Animal", typeof(cat))] 
public List<animal> Animals { get; set; } 

और इस ठीक से काम करता, जैसा कि मैंने, यह करना चाहते हैं जब तक मैं केवल बिल्लियों का उपयोग करें। दोबारा, जिस मिश्रण में मैं मिश्रण में मछली डालता हूं, वह उसी त्रुटि (मछली की अपेक्षा नहीं) के साथ उड़ाता है।

मैं कई typeof जोड़ सकते हैं विशेषताएं:

[XmlElement("Animal")] 
[XmlElementAttribute(typeof(cat))] 
[XmlElementAttribute(typeof(fish))] 
public List<animal> Animals { get; set; } 

और इस संकलित, लेकिन तत्व नाम पर ध्यान नहीं देता है, और <cat> </cat> और <fish> </fish>, क्रमशः, जो अस्वीकार्य है के रूप में वस्तुओं को धारावाहिक।

मैं यहां तक ​​कि कई [XmlElement] टैग जोड़ने की कोशिश की है:

[XmlElement("Animal", typeof(cat))] 
[XmlElement("Animal", typeof(fish))] 
public List<animal> Animals { get; set; } 

इसे कोई दूसरा अपवाद, इस बार है कि वस्तुओं "बिल्ली" और "मछली" दोनों में टाइप करें "पशु" का उपयोग फेंकता वही दायरा

क्या कोई इस बारे में सोच सकता है?

अद्यतन थोड़ा और अधिक खुदाई बाद, मैंने पाया This SO post जो आधार वर्ग के लिए नाम स्थान जोड़ने का सुझाव:

[XmlRoot(Namespace="myNamespace")] 
[XmlInclude(typeof(cat))] 
[XmlInclude(typeof(fish))] 
public abstract class animal 

इस Serializing निम्नलिखित पैदावार:

<animal xsi:type="cat" type="cat"> 
    ... 
</animal> 
<animal xsi:type="fish" type="fish"> 
    ... 
</animal> 

कहाँ xsi: टाइप = "बिल्ली" कक्षा के नाम को संदर्भित करता है, और प्रकार = "बिल्ली" उस प्रकार की विशेषता विशेषता को संदर्भित करता है बेस क्लास के भीतर (बहुत ही शीर्ष उदाहरण देखें)। यह है जो मुझे चाहिए को बंद करें, और मुझे डर है कि मैं यहां अनुभवहीनता से पीड़ित हो सकता हूं, लेकिन क्या xsi से छुटकारा पाने का कोई तरीका है: विशेषता विशेषता सूची?

+0

मैंने आपका शीर्षक संपादित किया है। कृपया देखें, "[प्रश्नों में उनके शीर्षक में" टैग "शामिल होना चाहिए?] (Http://meta.stackexchange.com/questions/19190/)", जहां आम सहमति है "नहीं, उन्हें नहीं करना चाहिए"। –

+0

क्षमा करें, मैंने दिशानिर्देशों में उस बिट को याद किया। सर उठाने के लिए धन्यवाद। – JesseF

+0

एक आंशिक समाधान मिला, विवरण के लिए नीचे दिए गए अद्यतन को देखें – JesseF

उत्तर

3

अपने आधार वर्ग के लिए XmlInclude गुण जोड़ने से इस serilazation मुद्दा

[Serializable] 
    [XmlInclude(typeof(cat))] 
    [XmlInclude(typeof(fish))] 
    class animals 
    { 
     .... 
    } 

    public class cat:animals 
    { 
     public string size { get; set; } 
     public string furColor { get; set; } 
    } 

    public class fish:animals 
    { 
     public string size { get; set; } 
     public string scaleColor { get; set; } 
    } 

अद्यतन

यहाँ एक संक्षिप्त उदाहरण है कि मेरे पक्ष में काम करता है, आप वास्तव में करने के लिए प्रकार विशेषता की जरूरत नहीं है है का समाधान करना चाहिए मेरी राय क्योंकि आप इसे typeof() विधि से पुनर्प्राप्त कर सकते हैं। जब तक कि प्रकार की विशेषता का कोई अन्य उद्देश्य न हो। इस (कोई विकल्प के साथ बहुत ही बुनियादी क्रमबद्धता) में

 List<animal> animals = new List<animal>(); 
     cat catofdoom = new cat(); 
     catofdoom.furColor = "brown"; 
     catofdoom.size = "10 pounds"; 
     animals.Add(catofdoom); 

     fish fishofdoom = new fish(); 
     fishofdoom.scaleColor = "blue"; 
     fishofdoom.size = "12 inches"; 
     animals.Add(fishofdoom); 


     try 
     { 
      XmlSerializer xs = new XmlSerializer(typeof(List<animal>)); 
      using (StreamWriter wr = new StreamWriter("animal.xml")) 
      { 
       xs.Serialize(wr, animals); 
      } 
     } 
     catch (Exception e) 
     { 

      throw; 
     } 

परिणाम:

<?xml version="1.0" encoding="utf-8"?> 
<ArrayOfAnimal xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> 
    <animal xsi:type="cat"> 
    <size>10 pounds</size> 
    <furColor>brown</furColor> 
    </animal> 
    <animal xsi:type="fish"> 
    <size>12 inches</size> 
    <scaleColor>blue</scaleColor> 
    </animal> 
</ArrayOfAnimal> 
+0

मैंने कोशिश की, और यह अभी भी मुझे त्रुटि देता है "टाइप बिल्ली की अपेक्षा नहीं की गई थी। XmlInclude या SoapInclude विशेषता का उपयोग उन प्रकारों को निर्दिष्ट करने के लिए करें जो स्थिर रूप से ज्ञात नहीं हैं।" यह बिल्कुल ऊपर के रूप में दर्ज किया गया है। क्या मुझे कुछ और याद आ रहा है? – JesseF

+0

मुझे जिक्र करना चाहिए कि मैं एक .NET 4.5 वेबएपीआई समाधान का उपयोग कर रहा हूं। मैं Legrandviking, उपर्युक्त समाधान _should_ काम से सहमत हूँ। क्या हम दोनों कुछ गलत कर रहे हैं? मैं "बग" ध्वज लहर करने में संकोच कर रहा हूं, क्या कोई इस काम की तरह कुछ करने में कामयाब रहा है? – JesseF

+0

मैंने अपना मूल उत्तर अपडेट किया है। उम्मीद है कि यह आपकी ज़रूरत के अनुरूप होगा – legrandviking

1

मैं DataContractSerializer का उपयोग करने और serializer में जाना जाता है प्रकार में शामिल हैं सुझाव देते हैं। XmlInclude का उपयोग encasulation सिद्धांत के लिए एक ब्रेक का प्रकार है। कुछ नमूने के लिए प्रदत्त एमएसडीएन लिंक देखें ...

+0

मैं जस्टर से सहमत हूं, और अधिक लचीला है और हर serilizable सदस्य को सार्वजनिक होने की आवश्यकता नहीं है – legrandviking

+0

हम्म ... यह पूरी वस्तु के एक रिफैक्टर की आवश्यकता होगी ... यहाँ हम जाओ! यदि यह काम करता है तो मैं आपको एक या दो दिन में बता दूंगा :) – JesseF

+0

ठीक है, अगर मेरा शोध सही है, तो मैं डेटाकंट्रैक्टसेरियलाइज़र का उपयोग नहीं कर सकता, क्योंकि मुझे विशेषताओं का उपयोग करने में सक्षम होना चाहिए, इसलिए मैं XMLSerializer के साथ फंस गया हूं । जो मुझे कुछ बाहरी गुणों से छुटकारा पाने के लिए वापस लाता है। – JesseF

1

आपको दोनों की आवश्यकता है!

[Serializable] 
[XmlInclude(typeof(cat))] 
[XmlInclude(typeof(fish))] 
class animals 
{ 
    .... 
} 

public class cat:animals 
{ 
    public string size { get; set; } 
    public string furColor { get; set; } 
} 

public class fish:animals 
{ 
    public string size { get; set; } 
    public string scaleColor { get; set; } 
} 

XmlElement नाम में मामूली परिवर्तन ध्यान दें। यह अभी सही ढंग से काम करेगा।

[XmlElement("cat", typeof(cat))] 
[XmlElement("fish", typeof(fish))] 
public List<animal> Animals { get; set; } 
+0

यह वास्तव में प्रश्न का उत्तर देता है। – CSharper

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