1

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

The function Serialize is not working with my existing List, but i dont know why. I already tried to compile it but i get an error wich says, that the methode needs an object refference.

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;
        }
    }
}

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

Daniel Bucher
  • 25
  • 1
  • 6
  • it would help if you could post the serialization error you get. It would also be wise to try and make sense of the error by analyzing [inner errors in a try catch](https://stackoverflow.com/questions/22826067/what-is-inner-exception). You can also try to follow [this tutorial on list serialization](https://www.dotnetperls.com/serialize-list) – Bennett Yeo Mar 10 '17 at 06:19
  • Now what is the problem? You didn't mention in the post – J.SMTBCJ15 Mar 10 '17 at 06:19
  • Side note: please avoid text unrelated to the problem like "new here", "thank you", "I'm Bob the Third" (or any other signature). Instead make sure that code provided in the post follows [MCVE] guidelines and all necessary information like input/output/error message present in the post. – Alexei Levenkov Mar 10 '17 at 06:23

2 Answers2

0

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.

Bennett Yeo
  • 819
  • 2
  • 14
  • 28
  • Wow thank you for the great answer! This will help me as base for my program! If its ready to use u will get a Cocktail ;) :D – Daniel Bucher Mar 10 '17 at 08:23
0

You'd better use ExtendedXmlSerializer to serialize and deserialize.

Instalation You can install ExtendedXmlSerializer from nuget or run the following command:

Install-Package ExtendedXmlSerializer

Serialization:

ExtendedXmlSerializer serializer = new ExtendedXmlSerializer();
var list = new List<Cocktail>();
var xml = serializer.Serialize(list);

Deserialization

var list = serializer.Deserialize<List<Cocktail>>(xml);

Standard XML Serializer in .NET is very limited.

  • Does not support serialization of class with circular reference or class with interface property,
  • Does not support Dictionaries,
  • There is no mechanism for reading the old version of XML,
  • If you want create custom serializer, your class must inherit from IXmlSerializable. This means that your class will not be a POCO class,
  • Does not support IoC.

ExtendedXmlSerializer can do this and much more.

ExtendedXmlSerializer support .NET 4.5 or higher and .NET Core. You can integrate it with WebApi and AspCore.