views:

273

answers:

4

I am try to deserialize my class, that normally serialized.

public class MyClass
{
   private List<Section> sections = new List<Section>();
   public List<Section> Sections
   {
        get
        {
          return this.sections;
        }
   }
}

public class Section1: Section
{
    public string MyProperty {get;set;}
}

public class Section2 : Section
{
    public string MyProperty2 {get;set;}
}

I serialize the class MyClass without error , but when I try deserialize it , I received a class MyClass with empty property in Section (This property was empty)!

Why is this, how to solve this problem?

Example xml :

<MyClass>
  <Sections>
     <Section1> 
       <MyProperty>foo1</MyProperty>
     </Section1>
     <Section1> 
       <MyProperty>foo2</MyProperty>
     </Section1>
     <Section2> 
       <MyProperty2>boo1</MyProperty2>
     </Section2>
  </Sections>
</MyClass>

Serialize and Deserialize Code:

Class that used for serialization/deserialization:

public class ObjectSerializer
{
    private readonly XmlAttributeOverrides xmlAttributeOverrides = new XmlAttributeOverrides();

    public void XmlSerialize<T>(T value, TextWriter outStream)
    {
        Type type = typeof (T);
        object[] result = type.GetCustomAttributes(typeof (SerializableAttribute), true);
        if (result != null)
        {
            var serializer = new XmlSerializer(type, this.xmlAttributeOverrides);
            serializer.Serialize(outStream, value);
        }
    }

    public T XmlDeserialize<T>(string xml)
    {
        var textReader = new XmlTextReader(new StringReader(xml));
        var xmlSerializer = new XmlSerializer(typeof(T));

        var result = xmlSerializer.Deserialize(textReader);
        return (T)result;
    }


    public void ExportOverridesFrom<TAssemply, TBaseType, TObject>(
        Expression<Func<TObject, object>> propertySelector)
    {
        IEnumerable<Type> inheritedTypes = typeof (TAssemply).Assembly.GetTypes().Where(t => t.BaseType == typeof (TBaseType));
        var xmlAttributes = new XmlAttributes();
        foreach (Type type in inheritedTypes)
        {
            var xmlElementAttribute = new XmlElementAttribute {Type = type};
            xmlAttributes.XmlElements.Add(xmlElementAttribute);
        }
        PropertyInfo objectProperty = Reflect<TObject>.GetProperty(propertySelector);
        this.xmlAttributeOverrides.Add(typeof (TObject), objectProperty.Name, xmlAttributes);
    }
}

Serialization: all good!

var objectSerializer = new ObjectSerializer();
objectSerializer.ExportOverridesFrom<Section1, Section, MyClass>(p => p.Sections);
objectSerializer.XmlSerialize(myClass, resultStream);

Deserializatoin: Everything bad!

 xml - result serialization.
 var result = objectSerializer.XmlDeserialize<MyClass>(xml);

Thanks, Oksana

A: 

You'll need to instantiate the List<Section> sections to an empty list before you use it.

Jeremy McGee
I instantiate a Property but the result is the same
Oksana
A: 

You will need to change the declaration of the private sections member to:

private List<Section> sections = new List<Section>();

Otherwise it will be null and cannot be assigned to.

In addition, your Sections property only has a Getter - it needs a setter or it will never get set:

public List<Section> Sections
{
    get
    {
      return this.sections;
    }

    set
    {
      this.sections = value;
    }

}
Oded
It does not solve the problem. Setter is not neededWhen I add in the property - (which has only a setter) not heirs, and the base classes themselves, then all is well.But I try to add a setter, nothing has changed.
Oksana
A: 

I've got to solve this problem!

When to create a serializer, in the constructor pass xmlAttributeOverrides. (i.e. the same as in the serialization).

 public T XmlDeserialize<T>(string xml)
    {
        var textReader = new XmlTextReader(new StringReader(xml));
        var xmlSerializer = new XmlSerializer(typeof(T), xmlAttributeOverrides); <--this

        var result = xmlSerializer.Deserialize(textReader);
        return (T)result;
    }

It work!

Oksana
A: 
[DataContract]
[KnownType(typeof(Section1))]
[KnownType(typeof(Section2))]
public class Section
{ 

} 

Try using DataContract serializer and you can pass in derived types

Serializing:

DataContractSerializer ser = new DataContractSerializer(typeof(Section),new Type[] { typeof(Section1),typeof(Section2)});
     ser.WriteObject(writer, sectionObj);
 writer.Close();

De-serializing:

DataContractSerializer deser = new DataContractSerializer(typeof(Section),new Type[] { typeof(Section1),typeof(Section2)}););            
Section deserialisedSection = (Section)deser.ReadObject(reader, true);
chugh97