2009-12-30 8 views
7

मैं एक कक्षा को क्रमबद्ध करने की कोशिश कर रहा हूं जो बेस क्लास से विरासत में आता है जो IXmlSerializable लागू करता है।बेस क्लास में IXmlSerializable को कार्यान्वित करते समय वापस 'डिफ़ॉल्ट' एक्सएमएल क्रमिकरण पर वापस कैसे करें?

संपत्ति वर्ग नामक बेस क्लास एक कक्षा है जो गतिशील गुणों (credits to Marc Gravell) की अनुमति देती है।

मैंने IXmlSerializable लागू किया ताकि गतिशील गुण (एक शब्दकोश में संग्रहीत) सामान्य xml तत्वों के रूप में लिखे जाएं।

उदा। निम्नलिखित कार्यान्वयन के साथ काम करने के लिए

<Person> 
    <Name>Tim</Name> 
    <DynamicProperties> 
    <Country> 
     <string>USA</string> 
    </Country> 
    </DynamicProperties> 
<Person> 

मैं हिस्सा प्राप्त कर सकते हैं: जब एक सार्वजनिक संपत्ति (गैर गतिशील) नाम और एक गतिशील संपत्ति उम्र के साथ एक कक्षा व्यक्ति serializing, मैं इसे निम्न XML उत्पन्न करने के लिए के लिए चाहते हैं आधार PropertyBag कक्षा में WriteXml की:

public void WriteXml(System.Xml.XmlWriter writer) 
    { 
     writer.WriteStartElement("DynamicProperties"); 

     // serialize every dynamic property and add it to the parent writer 
     foreach (KeyValuePair<string, object> kvp in properties) 
     { 
      writer.WriteStartElement(kvp.Key); 

      StringBuilder itemXml = new StringBuilder(); 
      using (XmlWriter itemWriter = XmlWriter.Create(itemXml)) 
      { 
       // serialize the item 
       XmlSerializer xmlSer = new XmlSerializer(kvp.Value.GetType()); 
       xmlSer.Serialize(itemWriter, kvp.Value);      

       // read in the serialized xml 
       XmlDocument doc = new XmlDocument(); 
       doc.LoadXml(itemXml.ToString()); 

       // write to modified content to the parent writer 
       writer.WriteRaw(doc.DocumentElement.OuterXml); 
      } 

      writer.WriteEndElement(); 
     } 

     writer.WriteEndElement(); 
    } 

हालांकि, जब व्यक्ति वर्ग serializing, तो वह अब सामान्य (गैर गतिशील) गुण serializes जब तक कि मैं व्यक्ति (जो मैं नहीं करना चाहता हूँ में WriteXml विधि के ऊपर लिख)। क्या कोई तरीका है कि बेस क्लास में मैं स्वचालित रूप से स्थैतिक गुण जोड़ सकता हूं? मुझे पता है कि मैं इसे प्रतिबिंब का उपयोग करके मैन्युअल रूप से कर सकता हूं, लेकिन मैं सोच रहा था कि नेट फ्रेमवर्क में कुछ अंतर्निहित कार्यक्षमता है या नहीं?

+0

मुझे लगता है कि आपको "स्थैतिक" शब्द से बचना चाहिए, क्योंकि इसका दूसरा (बहुत अलग) अर्थ है ... –

उत्तर

1

मार्क, एक अलग संग्रह में FixedProperties डाल पर अपने जवाब मिल गया मुझे उस सोच के बजाय इनहेरिट PropertyBag से, मुझे उस प्रकार की संपत्ति बनाना चाहिए।

इसलिए मैंने एक प्रॉपर्टीबैगप्रैपर क्लास बनाया जिसकी मेरी व्यक्तिगत श्रेणी से विरासत मिली और यह काम करता है।

[Serializable] 
[TypeDescriptionProvider(typeof(PropertyBagDescriptionProvider))]  
public abstract class PropertyBagWrapper 
{ 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)]  
    public PropertyBag DynamicProperties { get; set; } 

    public object this[string name] 
    { 
     get { return DynamicProperties[name]; } 
     set { DynamicProperties[name] = value; } 
    } 
    protected PropertyBagWrapper() 
    { 
     DynamicProperties = new PropertyBag(this.GetType()); 
    } 
} 

[Serializable]  
public class Person : PropertyBagWrapper 
{ 
    [Browsable(true)] 
    public string Name { get; set; } 
} 

मैं PropertyBag और ICustomTypeDescriptor कार्यान्वयन के लिए आवश्यक कस्टम कक्षाओं के लिए सभी कोड को दोहराना नहीं होगा, तो आप उस here पा सकते हैं।

मैंने प्रॉपर्टीबैग क्लास से PropertyBagWrapper क्लास में TypeDescriptionProvider विशेषता को स्थानांतरित किया था।

प्रॉपर्टीबैग क्लास अभी भी प्रश्न में पोस्ट किए गए WriteXml() विधि के लिए एक ही कार्यान्वयन है।

3

मैंने XmlSerializer (और कई अन्य धारावाहिक API) के साथ काफी समय बिताया है, और मुझे पूरा यकीन है कि बस: आप नहीं कर सकते। कार्यान्वित IXmlSerializable सभी या कुछ भी नहीं है।

सबसे नज़दीकी मैं सोच सकता हूं कि सभी निश्चित गुणों को एक उप-वस्तु में धोखा देना और स्थानांतरित करना; यह आपको थोड़ा अलग एक्सएमएल देगा - कुछ ऐसा:

<FixedProperties> 
    <Name>Tim</Name> 
</FixedProperties> 
<DynamicProperties> 
    <Country> 
    <string>USA</string> 
    </Country> 
</DynamicProperties> 

लेकिन मुझे उम्मीद है कि यह काम करेगा। आपके बेस ऑब्जेक्ट पर पास-थ्रू गुण होंगे:

[Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
public FixedProperties FixedProps {get;set;} 
public string Name { 
    get {return FixedProps.Name;} 
    set {FixedProps.Name = value;} 
} 

समझ में आता है? आप Name को [XmlIgnore] के रूप में भी चिह्नित कर सकते हैं, लेकिन यह बहुत अनावश्यक लगता है। अपने bespoke serialize विधि में आप उपयोग करेंगे new XmlSerializer(typeof(FixedProperties))

संपादित करें: यहाँ एक काम "को क्रमानुसार" उदाहरण है:

using System; 
using System.ComponentModel; 
using System.Xml.Serialization; 

static class Program 
{ 
    static void Main() 
    { 
     MyType obj = new MyType { Name = "Fred" }; 
     var ser = new XmlSerializer(obj.GetType()); 
     ser.Serialize(Console.Out, obj); 
    } 
} 
public class MyType : IXmlSerializable 
{ 
    public MyType() 
    { 
     FixedProperties = new MyTypeFixedProperties(); 
    } 
    [Browsable(false), EditorBrowsable(EditorBrowsableState.Never)] 
    public MyTypeFixedProperties FixedProperties { get; set; } 
    [XmlIgnore] 
    public string Name 
    { 
     get { return FixedProperties.Name; } 
     set { FixedProperties.Name = value; } 
    } 

    System.Xml.Schema.XmlSchema IXmlSerializable.GetSchema() 
    { 
     return null; 
    } 

    void IXmlSerializable.ReadXml(System.Xml.XmlReader reader) 
    { 
     throw new System.NotImplementedException(); 
    } 

    void IXmlSerializable.WriteXml(System.Xml.XmlWriter writer) 
    { 
     writer.WriteStartElement("DynamicProperties"); 
     writer.WriteElementString("Foo", "Bar"); 
     writer.WriteEndElement(); 
     fixedPropsSerializer.Serialize(writer, FixedProperties); 
    } 
    static readonly XmlSerializer fixedPropsSerializer 
     = new XmlSerializer(typeof(MyTypeFixedProperties)); 

} 
[XmlRoot("FixedProperties")] 
public class MyTypeFixedProperties 
{ 
    public string Name { get; set; } 
} 
+0

पैसे पर सही। यही कारण है कि डेटाकंट्रैक्ट सामान .NET के नए संस्करणों में जोड़ा गया था। यही कारण है कि "पुरानी" एएसएमएक्स वेब सेवाएं भी उड़ती हैं, क्योंकि आप पूरी तरह से स्क्रैच से धारावाहिक लिखने के बिना अपनी वस्तुओं के क्रमबद्धता का पता नहीं लगा सकते हैं। – jvenema

+0

यह काम करना चाहिए, लेकिन मेरे इरादे के उद्देश्य से नहीं। व्युत्पन्न कक्षाएं पहले से मौजूद हैं, मैं बस उन्हें गतिशील गुणों के लिए कार्यक्षमता जोड़ना चाहता था। निश्चित गुण व्युत्पन्न वर्ग में रहना चाहिए। हालांकि मैं इनपुट की बहुत सराहना करता हूं! – Timmel

+0

@jvenema - क्या यह डेटाकंट्रैक्ट विशेषताओं का उपयोग करके संभव होगा और यदि ऐसा है, तो क्या आपके पास मेरे लिए कोई अच्छा संकेतक है? – Timmel

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