यह केवल घोषणात्मक क्रमांकन की एक अंतर्निहित सीमा है जहां प्रकार की जानकारी आउटपुट के भीतर एम्बेडेड नहीं होती है।
<Flibble Foo="10" />
वापस में बदलने की कोशिश कर रहा है
public class Flibble { public object Foo { get; set; } }
धारावाहिक कैसे जानता है कि क्या यह एक इंट, एक स्ट्रिंग, एक डबल (या कुछ और) होना चाहिए ...
इस काम को करने के लिए आपके पास कई विकल्प हैं, लेकिन अगर आप वास्तव में रनटाइम तक नहीं जानते हैं तो ऐसा करने का सबसे आसान तरीका XmlAttributeOverrides का उपयोग करना है ।
अफसोस की बात है कि यह केवल आधार वर्गों के साथ काम करेगा, इंटरफेस नहीं। आप जो सबसे अच्छा कर सकते हैं, वह संपत्ति की अनदेखी करना है जो आपकी आवश्यकताओं के लिए पर्याप्त नहीं है।
यदि आपको वास्तव में इंटरफेस के साथ रहना चाहिए तो आपके पास तीन वास्तविक विकल्प होंगे:
इसे छिपाएं और किसी अन्य संपत्ति में इससे निपटें
बदसूरत, अप्रिय बॉयलर प्लेट और बहुत दोहराव लेकिन वर्ग के अधिकांश उपभोक्ताओं को समस्या से नहीं जूझना पड़ेगा:
[XmlIgnore()]
public object Foo { get; set; }
[XmlElement("Foo")]
[EditorVisibile(EditorVisibility.Advanced)]
public string FooSerialized
{
get { }
set { }
}
यह एक रखरखाव दुःस्वप्न बनने की संभावना है ...
IXmlSerializable लागू करें
इसमें पहले विकल्प की तरह ही आप चीजों पर पूर्ण नियंत्रण रखते हैं लेकिन
- पेशेवरों
- आपके आस-पास लटकने वाले 'नकली' गुण नहीं हैं।
- आप लचीलेपन / संस्करण को जोड़कर सीधे xml संरचना के साथ बातचीत कर सकते हैं
- विपक्ष
- आप वर्ग के अन्य सभी गुणों के लिए पहिया को फिर से लागू करने के लिए समाप्त हो सकते हैं
प्रयास के दोहराव के मुद्दे पहले के समान हैं।
रैपिंग प्रकार का उपयोग करने के लिए अपनी संपत्ति को संशोधित करें
public sealed class XmlAnything<T> : IXmlSerializable
{
public XmlAnything() {}
public XmlAnything(T t) { this.Value = t;}
public T Value {get; set;}
public void WriteXml (XmlWriter writer)
{
if (Value == null)
{
writer.WriteAttributeString("type", "null");
return;
}
Type type = this.Value.GetType();
XmlSerializer serializer = new XmlSerializer(type);
writer.WriteAttributeString("type", type.AssemblyQualifiedName);
serializer.Serialize(writer, this.Value);
}
public void ReadXml(XmlReader reader)
{
if(!reader.HasAttributes)
throw new FormatException("expected a type attribute!");
string type = reader.GetAttribute("type");
reader.Read();
if (type == "null")
return;
XmlSerializer serializer = new XmlSerializer(Type.GetType(type));
this.Value = (T)serializer.Deserialize(reader);
reader.ReadEndElement();
}
public XmlSchema GetSchema() { return(null); }
}
इसके इस्तेमाल से कुछ ऐसा होगा (प्रोजेक्ट P में):
public namespace P
{
public interface IFoo {}
public class RealFoo : IFoo { public int X; }
public class OtherFoo : IFoo { public double X; }
public class Flibble
{
public XmlAnything<IFoo> Foo;
}
public static void Main(string[] args)
{
var x = new Flibble();
x.Foo = new XmlAnything<IFoo>(new RealFoo());
var s = new XmlSerializer(typeof(Flibble));
var sw = new StringWriter();
s.Serialize(sw, x);
Console.WriteLine(sw);
}
}
जो आपको देता है:
<?xml version="1.0" encoding="utf-16"?>
<MainClass
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Foo type="P.RealFoo, P, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
<RealFoo>
<X>0</X>
</RealFoo>
</Foo>
</MainClass>
यह स्पष्ट रूप से वर्ग के उपयोगकर्ताओं के लिए अधिक बोझिल है, हालांकि बहुत बॉयलर प्लेट से बचा जाता है।
एक खुशहाल माध्यम हो सकता है कि XmlAnything के विचार को पहली तकनीक की 'बैकिंग' संपत्ति में मिला दिया जाए। इस तरह से अधिकांश ग्रंट कार्य आपके लिए किए जाते हैं लेकिन वर्ग के उपभोक्ताओं को आत्मनिरीक्षण के साथ भ्रम से परे कोई प्रभाव नहीं पड़ता है।