Search code examples
c#xmlserializationdeserialization

De-/serialization with a list of objects


I try to save and read multiple objects in one XML-File.

The function Serialize is not working with my existing List, but I don't know why. I already tried to compile it but I get an error which says, that the method needs an object reference.

Program.cs:

    class Program
    {
        static void Main(string[] args)
        {
            List<Cocktail> lstCocktails = new List<Cocktail>();
            listCocktails.AddRange(new Cocktail[]
            {
                new Cocktail(1,"Test",true,true,
                new Cocktail(1, "Test4", true, true, 0)
        });


            Serialize(lstCocktails);

        }

        public void Serialize(List<Cocktail> list)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(List<Cocktail>));
            using (TextWriter writer = new StreamWriter(@"C:\Users\user\Desktop\MapSample\bin\Debug\ListCocktail.xml"))
            {
                serializer.Serialize(writer, list);
            }
        }

        private void DiserializeFunc()
        {
            var myDeserializer = new XmlSerializer(typeof(List<Cocktail>));
            using (var myFileStream = new FileStream(@"C:\Users\user\Desktop\MapSample\bin\Debug\ListCocktail.xml", FileMode.Open))
            {
                ListCocktails = (List<Cocktail>)myDeserializer.Deserialize(myFileStream);
            }
        }

Cocktail.cs:

    [Serializable()]
    [XmlRoot("locations")]
    public class Cocktail
    {

        [XmlElement("id")]
        public int CocktailID { get; set; }
        [XmlElement("name")]
        public string CocktailName { get; set; }
        [XmlElement("alc")]
        public bool alcohol { get; set; }
        [XmlElement("visible")]
        public bool is_visible { get; set; }
        [XmlElement("counter")]
        public int counter { get; set; }
        private XmlSerializer ser;

        public Cocktail() {
            ser = new XmlSerializer(this.GetType());
        }
        public Cocktail(int id, string name, bool alc,bool vis,int count)
        {
            this.CocktailID = id;
            this.CocktailName = name;
            this.alcohol = alc;
            this.is_visible = vis;
            this.counter = count;
        }
    }
}

I also think I messed something up with the DiserializeFunc().


Solution

  • You are very close to implementing the Cocktail class correctly, but I think you're confused about how to serialize Lists. Your implementation of a Cocktail object class is completely fine, just get rid of the list related functions.

    using System;
    using System.Xml.Serialization;
    
    namespace Serialization_Help
    {
        [Serializable()]
        [XmlRoot("locations")]
        public class Cocktail
        {
    
            [XmlElement("id")]
            public int CocktailID { get; set; }
            [XmlElement("name")]
            public string CocktailName { get; set; }
            [XmlElement("alc")]
            public bool alcohol { get; set; }
            [XmlElement("visible")]
            public bool is_visible { get; set; }
            [XmlElement("counter")]
            public int counter { get; set; }
            public Cocktail() {
    
            }
            public Cocktail(int id, string name, bool alc, bool vis, int count)
            {
                this.CocktailID = id;
                this.CocktailName = name;
                this.alcohol = alc;
                this.is_visible = vis;
                this.counter = count;
            }
        }
    }
    

    Now in your new function you want to serialize the list directly.

    using System.Collections.Generic;
    using System.IO;
    using System.Xml.Serialization;
    
    namespace Serialization_Help
    {
        class Program {
            static void Main(string[] args) {
                List<Cocktail> list = new List<Cocktail> {
                    new Cocktail(01, "rum and coke", true, true, 5),
                    new Cocktail(02, "water on the rocks", false, true, 3)
                };
                Serialize(list);
                List<Cocktail> deserialized = DiserializeFunc();
            }
    
            public static void Serialize(List<Cocktail> list) {
    
                XmlSerializer serializer = new XmlSerializer(typeof(List<Cocktail>));
                using (TextWriter writer = new StreamWriter(Directory.GetCurrentDirectory() + @"\ListCocktail.xml")) serializer.Serialize(writer, list);
            }
    
            private static List<Cocktail> DiserializeFunc() {
                var myDeserializer = new XmlSerializer(typeof(List<Cocktail>));
                using (var myFileStream = new FileStream(Directory.GetCurrentDirectory() + @"\ListCocktail.xml", FileMode.Open)) return (List<Cocktail>)myDeserializer.Deserialize(myFileStream);
            }
        }
    }
    

    Doing so should correctly print out the following .xml output:

    <?xml version="1.0" encoding="utf-8"?>
    <ArrayOfCocktail xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <Cocktail>
        <id>1</id>
        <name>rum and coke</name>
        <alc>true</alc>
        <visible>true</visible>
        <counter>5</counter>
      </Cocktail>
      <Cocktail>
        <id>2</id>
        <name>water on the rocks</name>
        <alc>false</alc>
        <visible>true</visible>
        <counter>3</counter>
      </Cocktail>
    </ArrayOfCocktail>
    

    Keep in mind that I have not provided implementation of any of the standard safety or null checks for the file. You'll have to check if the file exists yourself by using File.Exists(...) (see here for File.Exists implementation) and implement the correct try and catch cases and what your code will chose to do if it runs into serialization or input/outut errors.