.net - DataContractSerializer का उपयोग करके कोई नामस्थान के साथ ऑब्जेक्ट को सीरियल करना




xml-serialization namespaces (2)

आपको उन वर्गों को चिह्नित करने की आवश्यकता है जिन्हें आप इसके साथ क्रमबद्ध करना चाहते हैं:

[DataContract(Namespace="")]

उस स्थिति में, डेटा अनुबंध धारावाहिक आपके क्रमबद्ध ऑब्जेक्ट्स के लिए किसी भी नामस्थान का उपयोग नहीं करेगा।

न घुलनेवाली तलछट

मैं DataContractSerializer का उपयोग करके अनुक्रमित किसी ऑब्जेक्ट के XML प्रतिनिधित्व से XML नामस्थान कैसे निकालूं?

उस ऑब्जेक्ट को बहुत ही सरल आउटपुट XML पर क्रमांकित किया जाना चाहिए।

  • नवीनतम और सबसे बड़ा - .Net 4 बीटा 2 का उपयोग करना
  • ऑब्जेक्ट को deserialized होने की आवश्यकता नहीं होगी।
  • XML में कोई xmlns नहीं होना चाहिए: ... नाम स्थान Refs
  • अपवाद और ISubObject के किसी भी उपप्रकार का समर्थन करने की आवश्यकता है।
  • मूल वस्तु को बदलना बहुत मुश्किल होगा।

वस्तु:

 [Serializable] 
 class MyObj
 {
     string str;
     Exception ex;
     ISubObject subobj;
 } 

इसमें क्रमबद्ध करने की आवश्यकता है:

<xml>
  <str>...</str>
  <ex i:nil="true" />
  <subobj i:type="Abc">
     <AbcProp1>...</AbcProp1>
     <AbcProp2>...</AbcProp2>
  </subobj>
</xml>

मैंने इस कोड का उपयोग किया है:

private static string ObjectToXmlString(object obj)
{
    if (obj == null) throw new ArgumentNullException("obj");

    var serializer =
        new DataContractSerializer(
            obj.GetType(), null, Int32.MaxValue, false, false, null,
            new AllowAllContractResolver());

    var sb = new StringBuilder();
    using (var xw = XmlWriter.Create(sb, new XmlWriterSettings
    {
        OmitXmlDeclaration = true,
        NamespaceHandling = NamespaceHandling.OmitDuplicates,
        Indent = true
    }))
    {
        serializer.WriteObject(xw, obj);
        xw.Flush();

        return sb.ToString();
    }
}

इस लेख से मैंने एक DataContractResolver को अपनाया ताकि कोई उपप्रकार घोषित न किया जाए:

public class AllowAllContractResolver : DataContractResolver
{
    public override bool TryResolveType(Type dataContractType, Type declaredType, DataContractResolver knownTypeResolver, out XmlDictionaryString typeName, out XmlDictionaryString typeNamespace)
    {
        if (!knownTypeResolver.TryResolveType(dataContractType, declaredType, null, out typeName, out typeNamespace))
        {
            var dictionary = new XmlDictionary();
            typeName = dictionary.Add(dataContractType.FullName);
            typeNamespace = dictionary.Add(dataContractType.Assembly.FullName);
        }
        return true;
    }

    public override Type ResolveName(string typeName, string typeNamespace, Type declaredType, DataContractResolver knownTypeResolver)
    {
        return knownTypeResolver.ResolveName(typeName, typeNamespace, declaredType, null) ?? Type.GetType(typeName + ", " + typeNamespace);
    }
}

यदि आपका डिफ़ॉल्ट व्यवहार (जैसा कि वर्तमान में मैं करता हूं) को दरकिनार करते हुए आपका दिल निर्धारित होता है, तो आप एक कस्टम XmlWriter बनाते हैं जो नाम स्थान लिखने के लिए बायपास करता है।

using System.IO;
using System.Xml;

public class MyXmlTextWriter : XmlTextWriter
{
  public MyXmlTextWriter(Stream stream)
    : base(stream, null)
  {
  }

  public override void WriteStartElement(string prefix, string localName, string ns)
  {
    base.WriteStartElement(null, localName, "");
  }
}

फिर आपके लेखक उपभोक्ता में, निम्नलिखित की तरह कुछ:

var xmlDoc = new XmlDocument();
DataContractSerializer serializer = new DataContractSerializer(obj.GetType());
using (var ms = new MemoryStream())
{
  using (var writer = new MyXmlTextWriter(ms))
  {
    serializer.WriteObject(writer, obj);
    writer.Flush();
    ms.Seek(0L, SeekOrigin.Begin);
    xmlDoc.Load(ms);
  }
}

और आउटपुट में नाम स्थान की घोषणाएं होंगी, लेकिन इस तरह कोई उपयोग नहीं होगा:

<TestObject xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Items xmlns:d2p1="http://schemas.microsoft.com/2003/10/Serialization/Arrays">
    <string>Item1</string>
    <string>Item2</string>
  </Items>
</TestObject>




datacontractserializer