views:

58

answers:

2

Does anyone have an implementation for object serialization that support collections, such as ICollection, IEnumerable, IList, IDictionary?

Below is my implementation, and it’s not so clean.

[Serializable]
public abstract class IXmlable
{
    public virtual string ToXml()
    {
        Type type = GetType();
        PropertyInfo[] properties = type.GetProperties();

        string ret = "<" + type.Name + ">";
        foreach (PropertyInfo item in properties)
        {
            object value = item.GetValue(this, null);
            if (value is IConvertible)
                ret += ("<" + item.Name + ">" + (value as IConvertible).ToString(CultureInfo.GetCultureInfo("en-US")) + "</" + item.Name + ">").Replace("&", "&amp;");
            else
                ret += ("<" + item.Name + ">" + (value != null ? value.ToString() : String.Empty) + "</" + item.Name + ">").Replace("&", "&amp;");
        }
        ret += "</" + type.Name + ">";
        return ret;
    }

/// <summary>
/// A class for serializing objects
/// </summary>
public static class Serializer
{
    public static string ToXML<T>(this List<T> parameter)
    {
        return SerializeObject(parameter);
    }

    /// <summary>
    /// This function serialize object.
    /// </summary>
    /// <param name="parameters">The object to be serialize</param>
    /// <returns>Returns the XML presentation of serialized object</returns>
    public static string SerializeObject(params object[] parameters)
    {
        var doc = new XDocument(new XElement("root"));
        string swString = string.Empty;
        foreach (var parameter in parameters)
        {
            var list = parameter as IEnumerable;
            IXmlable xmlable;
            if (list != null)
            {
                Type type = list.GetType().GetGenericArguments()[0];
                if (type.BaseType != null && type.BaseType.Name == "IXmlable")
                {
                    string typeName = type.Name;
                    swString = "<?xml version=\"1.0\"?><ArrayOf" + typeName + " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"&gt;";
                    swString = list.Cast<IXmlable>().Aggregate(swString, (current, item) => current + item.ToXml());
                    swString += "</ArrayOf" + typeName + ">";
                }
            }
            else if ((xmlable = parameter as IXmlable) != null)
            {
                swString = xmlable.ToXml();
            }
            else
            {
                swString = Serialize(parameter);
            }

            doc.Root.Add(XDocument.Parse(swString).Root);
        }
        return doc.ToString();
    }

    /// <summary>
    /// Serializes the specified parameter.
    /// </summary>
    /// <param name="parameter">The parameter.</param>
    /// <returns></returns>
    private static string Serialize(object parameter)
    {
        using (var sw = new MemoryStream())
        {
            new XmlSerializer(parameter.GetType()).Serialize(sw, parameter);
            sw.Position = 0;
            var buffer = new byte[sw.Length];
            sw.Read(buffer, 0, (int)sw.Length);
            return Encoding.Default.GetString(buffer);
        }
    }
}
A: 

you should have methods like

private static void Save(T yourobject, Type[] extraTypesInyourObject, string path)
{
    using (TextWriter textWriter = new TextWriter(path))
    {
        XmlSerializer xmlSerializer = CreateXmlSerializer(extraTypes);
        xmlSerializer.Serialize(textWriter, yourobject);
    }
}

    private static XmlSerializer CreateXmlSerializer(Type[] extraTypes)
    {
        Type ObjectType = typeof(T);
        XmlSerializer xmlSerializer = null;
        if (extraTypes!=null)
        {
            xmlSerializer = new XmlSerializer(ObjectType, extraTypes);
        }
        else
        {
            xmlSerializer = new XmlSerializer(ObjectType);
        }

        return xmlSerializer;
    }
Kubi
Your code supports List, but not Dictionary.
Amir Rezaei
The type System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] is not supported because it implements IDictionary.
Amir Rezaei
if your dictionary is having your own class objects, you should add it to extraTypes type array... Type[] extraTypes = new Type[]{Dictionary<yourObject, object>} and then create the xml serializer.
Kubi
lets say your object you wanted to serialize is a collection of your own object type. Make a collection object which is having a property as Dictionary<yourObjectType, object> yourObjects;
Kubi
I tried with.var d = new Dictionary<string, string> { { "one", "apple" }, { "two", "orange" } };XML<Dictionary<string, string>>.SaveToDocumentFormat(d, new Type[] { typeof(Dictionary<string, string>) }, @"C:\1.xml");And I got:The type System.Collections.Generic.Dictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] is not supported because it implements IDictionary.
Amir Rezaei
A: 

DataContractSerializer seems to be the best object serializer for the time been. http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractserializer.aspx

Amir Rezaei