none
Problem with DataContractSerializer RRS feed

  • Question

  • hi all,

    my code:

    using System;
    using System.IO;
    using System.Xml;
    using System.Text;
    using System.Runtime.Serialization;
    using System.Collections.ObjectModel;
    
    namespace SerializerDemo
    {
        public class Program
        {
            private static ObservableCollection<Company> companies = new ObservableCollection<Company>();
    
            private static void Read()
            {
                string text;
    
                text = File.ReadAllText("TEST.xml");
                using (Stream stream = new MemoryStream())
                {
                    byte[] bytes = Encoding.UTF8.GetBytes(text);
                    stream.Write(bytes, 0, bytes.Length);
                    stream.Position = 0;
                    DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Company>));
                    companies = (ObservableCollection<Company>)serializer.ReadObject(stream);
                }
            }
    
            private static void Write()
            {
                string text;
    
                Company company = new Company() { Name = "1" };
                company.Employees = new ObservableCollection<Employee>();
                Employee employee = new Employee() { Name = "Stefano", Eta = "43" };
                company.Employees.Add(employee);
                employee = new Employee() { Name = "Alessio", Eta = "8" };
                company.Employees.Add(employee);
                companies.Add(company);
    
                DataContractSerializer serializer = new DataContractSerializer(typeof(ObservableCollection<Company>));
                using (var ms = new MemoryStream())
                {
                    using (var xmlWriter = XmlWriter.Create(ms, new XmlWriterSettings { Indent = true }))
                    {
                        serializer.WriteObject(xmlWriter, companies);
                    }
                    ms.Seek(0, SeekOrigin.Begin);
                    using (StreamReader reader = new StreamReader(ms))
                    {
                        text = reader.ReadToEnd();
                    }
    
                    File.WriteAllText("TEST.xml", text);
                }
            }
    
            static void Main(string[] args)
            {
                Write();
    
                //Read();
            }
        }
    
        [Serializable]
        public class Company
        {
            private ObservableCollection<Employee> employees;
            public ObservableCollection<Employee> Employees
            {
                get { return employees; }
                set
                {
                    employees = value;
                }
            }
    
            public string Name;
    
            public int EmployeesNumber;
        }
    
        [Serializable]
        public class Employee
        {
            public string Name;
    
            public string Eta;
    
            //public string Phone;
    
            //[OnDeserializing]
            //private void setDefaultPhone(StreamingContext c)
            //{
            //    Phone = "123";
            //}
        }
    }

    produce this XML file:

    <?xml version="1.0" encoding="utf-8"?>
    <ArrayOfCompany xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/SerializerDemo">
      <Company>
        <EmployeesNumber>0</EmployeesNumber>
        <Name>1</Name>
        <employees>
          <Employee>
            <Eta>43</Eta>
            <Name>Stefano</Name>
          </Employee>
          <Employee>
            <Eta>8</Eta>
            <Name>Alessio</Name>
          </Employee>
        </employees>
      </Company>
    </ArrayOfCompany>

    if you uncomment Phone and setDefaultPhone in Employee class and in Main comment Write and uncomment Read serialization process failed. Why ?

    My objective is Read this XML file (without change Write procedure) after add a new member in Employee class.

    Thursday, May 11, 2017 6:30 AM

All replies

  • Adding [OptionalField] to public string Phone should fix this.

    Alternatively, switch from [Serializable] to [DataContract] and add [DataMember] to each field; DataMemberAttribute.IsRequired would then default to false.

    Thursday, May 11, 2017 3:15 PM
  • Adding [OptionalField] to public string Phone should fix this.

    Alternatively, switch from [Serializable] to [DataContract] and add [DataMember] to each field; DataMemberAttribute.IsRequired would then default to false.


    Is exist equivalent [OptionalField] to apply at property ?
    Friday, May 12, 2017 6:12 AM
  • Is exist equivalent [OptionalField] to apply at property ?

    Not really. Look at how ClassDataContract.ImportDataMembers is implemented in Reference Source. If you use [Serializable], then both HasDataContract and isNonAttributedType are false, and it goes to line 975, which examines only fields of the class, not properties.

    (If the serializable class has a property like 'public int Prop { get; set; }', then the C# compiler generates a field '<Prop>k__BackingField' for it, and DataContractSerializer will attempt to serialize the field rather than the property, but that will cause an exception because the name of the field will not be valid for XML.)

    Friday, May 12, 2017 2:00 PM