2011-08-03 15 views
14

क्या XmlSerializer को आदिम वर्ग के सदस्यों (जैसे स्ट्रिंग गुण) को एक्सएमएल गुणों के रूप में क्रमबद्ध करने का कोई तरीका नहीं है, एक्सएमएल तत्वों के रूप में नहीं, के बिना प्रत्येक संपत्ति घोषणा के सामने [XmlAttribute] लिखना है? I.e. क्या कोई वैश्विक स्विच है जो XmlSerializer को सभी आदिम वर्ग के सदस्यों को एक्सएमएल विशेषताओं के रूप में क्रमबद्ध करने के लिए कहता है?XmlSerializer को डिफ़ॉल्ट रूप से तत्वों के बजाय गुण उत्पन्न करने का कारण कैसे बनें

मान लें कि हमारे पास निम्न वर्ग है:

public class Person 
{ 
    public string FirstName 
    { 
     ... 
    } 

    public string LastName 
    { 
     ... 
    } 
} 

फिर XmlSerializer डिफ़ॉल्ट रूप से इस कोड को उत्पन्न करता है:

<Person> 
    <FirstName>John</FirstName> 
    <LastName>Doe</LastName> 
</Person> 

जो मैं चाहता हूं, हालांकि, यह कोड है:

<Person FirstName="John" LastName="Doe"/> 

फिर से: मैं [XmlAttribute] के बिना ऐसा करना चाहता हूं (या XmlAttributeOverrides के बिना, जो और भी काम करेगा)।

एक संभावित समाधान एक सामान्य पोस्टप्रोसेसिंग चरण का उपयोग करना होगा जो तत्वों को तत्वों में परिवर्तित करने के लिए एक एक्सएसएलटी ट्रांसफॉर्म लागू करता है। लेकिन मुझे आश्चर्य है कि एक आसान समाधान है या नहीं।

+0

एनरिको का जवाब प्रश्न का समाधान प्रतीत होता है, लेकिन यह निश्चित रूप से अधिक जटिल और कम वांछनीय है जो आप टालना चाहते हैं। शायद आप हमें बता सकते हैं कि आप उन विधियों का उपयोग क्यों नहीं कर सकते हैं, ताकि हम जान सकें कि, विशेष रूप से, आप से परहेज कर रहे हैं? –

+0

मुझे बाहरी सिट्सम के साथ डेटा का आदान-प्रदान करने की आवश्यकता है जिसके लिए एक विशिष्ट XML प्रारूप की आवश्यकता है। उस प्रारूप में, सरल डेटा प्रकारों को गुणों के रूप में दर्शाया जाता है, जटिल डेटा प्रकार (उदा। सूचियां) विशेषता के रूप में दर्शाए जाते हैं।डेटा मॉडल में लगभग 50 वर्ग और 500 विशेषताएं हैं। मैं इससे बचना चाहता हूं कि मुझे प्रत्येक विशेषता के सामने [XmlAttribute] लिखना है। –

+0

@ केली डब्ल्यू इस मामले में एक ही स्थान (जैसे बेस क्लास) में सामान्य एक्सएमएल क्रमबद्धता तर्क होना निश्चित रूप से समझ में आता है, क्योंकि यह चीजें रखता है [DRY] (http://en.wikipedia.org/wiki/Don't_repeat_yourself)। –

उत्तर

4

यह प्राप्त करने का एक तरीका IXmlSerializable इंटरफ़ेस लागू करता है जो बेस क्लास में क्रमबद्धता तर्क लागू करता है। कक्षाओं को एक्सएमएल में क्रमबद्ध करने के लिए, फिर कार्यक्षमता प्राप्त करने के लिए इस बेस क्लास से प्राप्त करना होगा।

यहाँ एक उदाहरण

public class XmlSerializableEntity : IXmlSerializable 
{ 
    public XmlSchema GetSchema() 
    { 
     // Implementation omitted for clarity 
    } 

    public void ReadXml(XmlReader reader) 
    { 
     // Implementation omitted for clarity 
    } 

    public void WriteXml(XmlWriter writer) 
    { 
     var properties = from property in this.GetType().GetProperties() 
         where property.PropertyType.IsPrimitive || 
           property.PropertyType == typeof(string) 
         select property; 

     foreach (var property in properties) 
     { 
      var name = property.Name; 
      var value = property.GetValue(this, null).ToString(); 
      writer.WriteAttributeString(name, value); 
     } 
    } 
} 

यहाँ हम Reflection उपयोग कर रहे हैं वर्तमान वस्तु, जिसका प्रकार से गुण की एक सूची प्राप्त करने के लिए एक आदिम या एक String है। इन गुणों को तब XML आउटपुट में प्रदत्त XmlWriter ऑब्जेक्ट का उपयोग करके विशेषताओं के रूप में लिखा जाता है।

कक्षाओं बस XmlSerializableEntity से इनहेरिट करना स्वचालित रूप से इस व्यवहार प्राप्त करना होगा, धारावाहिक की जानी चाहिए:

[Serializable] 
public class Foo : XmlSerializableEntity 
{ 
    public int Bar { get; set; } 
} 
+1

इस समाधान का नुकसान यह है कि अन्य एक्सएमएल सीरियलाइजेशन विशेषताओं जैसे [एक्सएमएलआईग्नोर] अब XmlSerializableEntity से व्युत्पन्न कक्षाओं में काम नहीं करेंगे (जब तक कि मैं XmlSerializableEntity में XmlSerializer करता है तो सभी विशेषता प्रसंस्करण को पुन: कार्यान्वित नहीं करता)। –

+0

@fmunkert वास्तव में, आपको [XmlIgnoreAttribute] (http://msdn.microsoft.com/en-us/library/system.xml.serialization.xmlignoreattribute.aspx) के लिए स्वयं को 'XmlSerializableEntity' में प्रतिबिंब के माध्यम से जांचना होगा) कक्षा। हालांकि केंद्रीय स्थान पर इस तरह के विशेष साझा व्यवहार होने से निश्चित रूप से भविष्य में संशोधन का लाभ होगा। –

+0

मैं इस समाधान को स्वीकार कर रहा हूं, क्योंकि यह मेरे प्रश्न का उत्तर देता है। हालांकि, मैं इसे लागू कर दूंगा, हालांकि, अलग-अलग क्योंकि एनरिको के समाधान के लिए बहुत अधिक काम की आवश्यकता होगी यदि मैं अभी भी सभी एक्सएमएल * विशेषता वर्गों का उपयोग करने में सक्षम होना चाहता हूं। मैं प्रतिबिंब का उपयोग करके गतिशील रूप से XmlAttributeOverrides उदाहरण उत्पन्न करने के बारे में सोच रहा हूं जो सभी आदिम गुणों को ओवरराइड करता है; या वैकल्पिक, मैं कोडडॉम का उपयोग कर प्रॉक्सी कक्षाओं को स्वतः उत्पन्न करने के लिए कोड लिख सकता हूं। –

0

मुझे लगता है कि XSLT सबसे अधिक स्थिर, रख-रखाव आसान और सुरुचिपूर्ण जाने का रास्ता है। इसे सब कुछ पुनः-बेसिंग की आवश्यकता नहीं है, पहले से परीक्षण किए गए क्रमबद्धता पर निर्भर करता है, कक्षा में 0mlमें xml कस्टम विशेषताओं की अनुमति देता है और संकलित ट्रांसफॉर्म के साथ स्मृति में किया जा सकता है।

यहाँ कुछ सामान्य xslt है कि यह करना चाहिए:

<?xml version=’1.0′ encoding=’utf-8′?> 
<xsl:stylesheet version=’1.0′ xmlns:xsl=’http://www.w3.org/1999/XSL/Transform’ xmlns:msxsl=’urn:schemas-microsoft-com:xslt’ exclude-result-prefixes=’msxsl’> 
<xsl:template match=’*'> 
<xsl:copy> 
<xsl:for-each select=’@*|*[not(* or @*)]‘> 
<xsl:attribute name=’{name(.)}’><xsl:value-of select=’.'/> 
</xsl:attribute> 
</xsl:for-each> 
<xsl:apply-templates select=’*[* or @*]|text()’/> 
</xsl:copy> 
</xsl:template> 
</xsl:stylesheet> 

कहा करने के बाद कि, मुझे आश्चर्य है अगर तत्वों विशेषताओं की तुलना में धीमी कर रहे हैं, खासकर जब रेखा के पार भेजा।

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