tags:

views:

509

answers:

4

I might have messed up on a design decision. Instead of using a strongly typed collection of custom objects, I have used a generic List. Essentially, what i have is:

public class AreaFields
{
    [XmlArray("Items")]
    [XmlArrayItem("Item")]
    public List<Fields> Fields { set; get; }

    [XmlAttribute]
    int id { set; get; }
}

public class Fields
{
    [XmlAttribute]
    public string Name { set; get; }
}

Throughout the application, I have used List<AreaFields> Now, I am in need of serializing the list into XML. What I am hoping to get is:

   <SomeXMLTag>
    <AreaFields id='1000'>
     <Items>
       <Item Name="Test1" />
       <Item Name="Test2" />
     </Items>
    </AreaFields>
    <AreaFields id='1001'>
     <Items>
       <Item Name="Test1" />
       <Item Name="Test2" />
     </Items>
    </AreaFields>
    </SomeXMLTag>

Since I cannot serialize List<> (or can I?), I will have to serialize every item of the list.

Ex: List<AreaFields> list = new List<AreaFields>();
//    more code to add to list
    list[0].GetRawXML(); //A method i have to serialize
+4  A: 

You can serialize List<>. Read here for the attributes I've used.

Jeremy Wilde
I've serialized generic lists too
Gabe Moothart
+5  A: 

You'll need a wrapper class; then serialize the instance of MyWrapper to get the xml as per your example.

[XmlRoot("SomeXMLTag")]
public class MyWrapper
{
    [XmlElement("AreaFields")]
    public List<AreaFields> AreaFields { get; set; }
}

public class AreaFields
{
    [XmlArray("Items")]
    [XmlArrayItem("Item")]
    public List<Fields> Fields { set; get; }

    [XmlAttribute]
    public int id { set; get; }
}

public class Fields
{
    [XmlAttribute]
    public string Name { set; get; }
}
Marc Gravell
A: 
using System;
using System.Collections.Generic;
using System.Xml;
using System.Xml.Serialization;
using System.Text;
using System.IO;

namespace Utils
{
    public class XMLSerializer
    {
        public static Byte[] StringToUTF8ByteArray(String xmlString)
        {
            return new UTF8Encoding().GetBytes(xmlString);
        }

        public static String SerializeToXML<T>(T objectToSerialize)
        {
            StringBuilder sb = new StringBuilder();

            XmlWriterSettings settings = 
                new XmlWriterSettings {Encoding = Encoding.UTF8, Indent = true};

            using (XmlWriter xmlWriter = XmlWriter.Create(sb, settings))
            {
                if (xmlWriter != null)
                {
                    new XmlSerializer(typeof(T)).Serialize(xmlWriter, objectToSerialize);
                }
            }

            return sb.ToString();
        }

        public static void DeserializeFromXML<T>(string xmlString, out T deserializedObject) where T : class
        {
            XmlSerializer xs = new XmlSerializer(typeof (T));

            using (MemoryStream memoryStream = new MemoryStream(StringToUTF8ByteArray(xmlString)))
            {
                deserializedObject = xs.Deserialize(memoryStream) as T;
            }
        }
    }
}

Then, when you want to print the list, do:

List<AreaFields> list = new List<AreaFields>();
//    more code to add to list
Console.WriteLine(Utils.XMLSerializer.SerializeToXML(areaFields));

EDIT: Changed serializer to avoid one of the binary conversions. You need to make sure all of the properties you want serialized are public, and that you have a constructor that takes no parameters as well.

Chris Doggett
You could just use a StringWriter as the source for XmlWriter, then call .ToString() - much easier, and no binary encoding/decoding to slow things down.
Marc Gravell
Good point. Also, it should be in its own namespace to avoid a conflict with System.Xml.Serialization.XmlSerializer, which I forgot to add when I pulled it out of my code.
Chris Doggett
A: 

Java generics work by type erasure. This kinda sorta means that when the app is actually running, the JVM doesn't care about generics. The compiler pays attention to them, then discards them from the bytecode (allthough certain annotations are put in the .class file etc etc)

So serialising and deserialising objects of a generic type is kind of a no-brainer. It deserialises as a List, and you cast it.

paulmurray