Dani
Dani

Reputation: 21

C# Serializing does not add values to attributes in xml file

I am new to programming but I need to serialize data, I first read a csv and create classes based on the data in said csv. When I click on a button the List should be serialized for later use.

This is the code for both the Dealership (del) and the Car class:

[DataContract]
public class Dealership
{
    [DataMember]
    private List<Car> carList = new List<Car>();
        
    public void ImportCars()
    {
        carList.Clear();

        var fileContent = string.Empty;
        var filePath = string.Empty;

        using (OpenFileDialog openFileDialog = new OpenFileDialog())
        {
            openFileDialog.InitialDirectory = "c:\\";
            openFileDialog.Filter = "csv files (*.csv)|*.csv";

            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                filePath = openFileDialog.FileName;

                using (var reader = new StreamReader(filePath))
                using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture))
                {
                    csv.Read();
                    csv.ReadHeader();
                    while (csv.Read())
                    {
                        var record = new Car
                        {
                            Model = csv.GetField("model"),
                            Brand = csv.GetField("brand"),
                            Year = Convert.ToInt32(csv.GetField("year")),
                            Price = Convert.ToDecimal(csv.GetField("price"))
                        };
                        carList.Add(record);
                    }
                }
            }
        }
    }
}

[DataContract]
public class Car
{
    [DataMember]
    private string brand;
    [DataMember]
    private string model;
    [DataMember]
    private int year;
    [DataMember]
    private decimal price;

    public string Brand { get; set; }

    public string Model { get; set; }

    public int Year { get; set; }

    public decimal Price { get; set; }
}

This is the form code:

Dealership del1 = del;

FileStream? fs = null;

try
{
    fs = new FileStream("dealership.xml", FileMode.OpenOrCreate, FileAccess.Write);

    Type mainType = typeof(Dealership);
    //List<Type> auxiliryTypes = new List<Type>() { typeof(Car), typeof(Customer) };
    DataContractSerializer dcs = new DataContractSerializer(mainType);

    dcs.WriteObject(fs, del1);
}
finally
{
    if (fs!=null) fs.Close();
}

Snippet of XML output:

<Dealership xmlns="http://schemas.datacontract.org/2004/07/Individual_Assignment" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><carList><Car><brand i:nil="true"/><model i:nil="true"/><price>0</price><year>0</year></Car>

How is it possible for the XML to not contain any values for the cars, when I sell a car by typing customer details in the form it does serialize those values but nothing else.

Upvotes: 2

Views: 46

Answers (1)

JonasH
JonasH

Reputation: 36556

As a rule of thumb, make your Data Transfer Object (DTO) classes (i.e. classes intended for serialization) have only public properties. You should probably also be using generic collections:

[DataContract] 
public class Dealership { 
    [DataMember] 
    public List<Car> CarList {get;set;} = new List<Car>();
}

Using public properties tend to work with most serialization libraries. There can be exceptions, some can handle private properties, some can handle immutable types, but then you need to check what specific syntax your library support. I do not remember the exact rules for DataContractSerializer.

Also note that your should probably separate your DTO classes from your domain classes, so you do not have to expose internal fields when actually using your objects, only when communicating with some other part of the system.

I would also advice setting up a unit test to serialize and deserialize your classes. That is an easy way to see what works and what does not. It can also be used to check that old versions of your classes still de serialize correctly if that is a concern for you.

Full example:

[DataContract]
public class Car
{
    [DataMember]
    public string Brand { get; set; }
    [DataMember]
    public string Model { get; set; }
    [DataMember]
    public int Year { get; set; }
    [DataMember]
    public decimal Price { get; set; }
}

[DataContract]
public class Dealership
{
    [DataMember] 
    public List<Car> Cars { get; set; } = new ();
};


[Test]
public void ShouldSerializeAndDeserialize()
{
    var sut = new DataContractXml();
    var car = new Car(){Brand = "Volvo", Model = "v70", Price = 20000, Year = 2004};
    var dealer = new Dealership();
    dealer.Cars.Add(car);

    using var ms = new MemoryStream();
    
    var serializer = new DataContractSerializer(typeof(Dealership));
    serializer.WriteObject(ms, dealer);
    ms.Position = 0;
    var result = (Dealership)serializer.ReadObject(ms);

    Console.WriteLine(result.Cars[0].Brand);
}

Upvotes: 2

Related Questions