खोज…


टिप्पणियों

HTML को पार्स करने के लिए XmlSerializer का उपयोग न करें। इसके लिए, विशेष लाइब्रेरीज़ HTML Agility Pack की तरह उपलब्ध हैं

वस्तु का सीरियलाइज़ करना

public void SerializeFoo(string fileName, Foo foo)
{
    var serializer = new XmlSerializer(typeof(Foo));
    using (var stream = File.Open(fileName, FileMode.Create))
    {
        serializer.Serialize(stream, foo);
    }
}

वशीकरण वस्तु

public Foo DeserializeFoo(string fileName)
{
    var serializer = new XmlSerializer(typeof(Foo));
    using (var stream = File.OpenRead(fileName))
    {
        return (Foo)serializer.Deserialize(stream);
    }
}

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

<Foo>
    <Dog/>
</Foo>
public class Foo
{
    // Using XmlElement
    [XmlElement(Name="Dog")]
    public Animal Cat { get; set; }
}

व्यवहार: संपत्ति के लिए मानचित्र का नाम (XmlArray)

<Store>
    <Articles>
        <Product/>
        <Product/>
    </Articles>
</Store>
public class Store
{
    [XmlArray("Articles")]
    public List<Product> Products {get; set; }
}

स्वरूपण: कस्टम दिनांक समय प्रारूप

public class Dog
{
    private const string _birthStringFormat = "yyyy-MM-dd";

    [XmlIgnore]
    public DateTime Birth {get; set;}

    [XmlElement(ElementName="Birth")]
    public string BirthString
    {
        get { return Birth.ToString(_birthStringFormat); }
        set { Birth = DateTime.ParseExact(value, _birthStringFormat, CultureInfo.InvariantCulture); }
    }
}

कुशलता से व्युत्पन्न प्रकारों के साथ कई धारावाहिकों का निर्माण करना

हम कहां से आए

कभी-कभी हम XmlSerializer ढांचे के लिए आवश्यक सभी मेटाडेटा आवश्यक नहीं प्रदान कर सकते हैं। मान लीजिए कि हमारे पास क्रमबद्ध वस्तुओं का एक आधार वर्ग है, और कुछ व्युत्पन्न वर्ग आधार वर्ग के लिए अज्ञात हैं। हम उन सभी वर्गों के लिए एक विशेषता नहीं रख सकते हैं जो आधार प्रकार के डिजाइन समय पर नहीं जानते हैं। हम व्युत्पन्न वर्गों में से कुछ को विकसित करने वाली एक अन्य टीम बना सकते हैं।

हम क्या कर सकते है

हम new XmlSerializer(type, knownTypes) उपयोग कर सकते हैं, लेकिन यह N धारावाहिकों के लिए O (N ^ 2) ऑपरेशन होगा, कम से कम तर्कों में दिए गए सभी प्रकारों की खोज करने के लिए:

// Beware of the N^2 in terms of the number of types.
var allSerializers = allTypes.Select(t => new XmlSerializer(t, allTypes));
var serializerDictionary = Enumerable.Range(0, allTypes.Length)
    .ToDictionary (i => allTypes[i], i => allSerializers[i])

इस उदाहरण में, बेस प्रकार इसके व्युत्पन्न प्रकारों से अवगत नहीं है, जो ओओपी में सामान्य है।

कुशलता से करना

सौभाग्य से, एक विधि है जो इस विशेष समस्या को संबोधित करती है - कुशलतापूर्वक कई धारावाहिकों के लिए ज्ञात प्रकारों की आपूर्ति:

System.Xml.Serialization.XmlSerializer.FromTypes विधि (प्रकार [])

FromTypes विधि आपको टाइप ऑब्जेक्ट्स की एक सरणी को संसाधित करने के लिए कुशलतापूर्वक XmlSerializer ऑब्जेक्ट्स की एक सरणी बनाने की अनुमति देती है।

var allSerializers = XmlSerializer.FromTypes(allTypes);
var serializerDictionary = Enumerable.Range(0, allTypes.Length)
    .ToDictionary(i => allTypes[i], i => allSerializers[i]);

यहाँ एक पूर्ण कोड नमूना है:

using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.Linq;
using System.Linq;
                    
public class Program
{
    public class Container
    {
        public Base Base { get; set; }
    }
    
    public class Base
    {
        public int JustSomePropInBase { get; set; }
    }
    
    public class Derived : Base
    {
        public int JustSomePropInDerived { get; set; }
    }
    
    public void Main()
    {
        var sampleObject = new Container { Base = new Derived() };
        var allTypes = new[] { typeof(Container), typeof(Base), typeof(Derived) };
        
        Console.WriteLine("Trying to serialize without a derived class metadata:");
        SetupSerializers(allTypes.Except(new[] { typeof(Derived) }).ToArray());
        try
        {
            Serialize(sampleObject);
        }
        catch (InvalidOperationException e)
        {
            Console.WriteLine();
            Console.WriteLine("This error was anticipated,");
            Console.WriteLine("we have not supplied a derived class.");
            Console.WriteLine(e);
        }
        Console.WriteLine("Now trying to serialize with all of the type information:");
        SetupSerializers(allTypes);
        Serialize(sampleObject);
        Console.WriteLine();
        Console.WriteLine("Slides down well this time!");
    }

    static void Serialize<T>(T o)
    {
        serializerDictionary[typeof(T)].Serialize(Console.Out, o);
    }

    private static Dictionary<Type, XmlSerializer> serializerDictionary;
    
    static void SetupSerializers(Type[] allTypes)
    {
        var allSerializers = XmlSerializer.FromTypes(allTypes);
        serializerDictionary = Enumerable.Range(0, allTypes.Length)
            .ToDictionary(i => allTypes[i], i => allSerializers[i]);
    }
}

आउटपुट:

Trying to serialize without a derived class metadata:
<?xml version="1.0" encoding="utf-16"?>
<Container xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
This error was anticipated,
we have not supplied a derived class.
System.InvalidOperationException: There was an error generating the XML document. ---> System.InvalidOperationException: The type Program+Derived was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write2_Base(String n, String ns, Base o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write3_Container(String n, String ns, Container o, Boolean isNullable, Boolean needType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriter1.Write4_Container(Object o)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle, String id)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces, String encodingStyle)
   at System.Xml.Serialization.XmlSerializer.Serialize(XmlWriter xmlWriter, Object o, XmlSerializerNamespaces namespaces)
   at Program.Serialize[T](T o)
   at Program.Main()
Now trying to serialize with all of the type information:
<?xml version="1.0" encoding="utf-16"?>
<Container xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
  <Base xsi:type="Derived">
    <JustSomePropInBase>0</JustSomePropInBase>
    <JustSomePropInDerived>0</JustSomePropInDerived>
  </Base>
</Container>
Slides down well this time!

आउटपुट में क्या है

यह त्रुटि संदेश अनुशंसा करता है कि हमने क्या बचने की कोशिश की (या कुछ परिदृश्यों में हम क्या नहीं कर सकते) - आधार वर्ग से व्युत्पन्न प्रकारों को संदर्भित करना:

Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

इस प्रकार हम XML में अपना व्युत्पन्न वर्ग प्राप्त करते हैं:

<Base xsi:type="Derived">

Base Container प्रकार में घोषित संपत्ति प्रकार से मेल खाता है, और Derived वास्तव में आपूर्ति किए गए उदाहरण का प्रकार है।

यहाँ एक काम करने का उदाहरण है बेला



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow