edwin the duck
edwin the duck

Reputation: 95

c# DataContractSerializer with inheritance

When Deserializing XML with the DataContractSerializer I'm having trouble with a sequence of a base class. None of the derived classes are deserialized from the XML:

<?xml version="1.0" encoding="utf-8" ?>

<Page xmlns="Renishaw.Page">
  <Fields>
    <Field Value="Welcome"/>
    <LanguageField Value="English"/>
  </Fields>

  <Buttons>
    <CancelButton/>
    <BackButton/>
    <NextButton/>
  </Buttons>

  <ChildPath>D:\SerializeTest\Console\bin\Debug\XML\Content\Next\Next\Page.xml</ChildPath>
</Page>

The following is my DataContract:

[DataContract(Namespace = "Renishaw.Page")]
internal class Page
{
    [DataMember(Order=1, IsRequired = true)]
    public List<Field> Fields { get; set; }

    [DataMember(Order = 2, IsRequired = true)]
    public List<Button> Buttons { get; set; }

    [IgnoreDataMember]
    public Page Child { get; set; }

    [DataMember(Order = 3, IsRequired = true)]
    private string ChildPath { get; set; }

    [OnDeserialized]
    private void OnDeserialized(StreamingContext context)
    {
        if (ChildPath.Equals(""))
            return;

        Child = Serializer.Deserialize<Page>(ChildPath);
    }

    [OnSerialized]
    private void OnSerialized(StreamingContext context)
    {

    }
}

[DataContract]
[KnownType(typeof(LanguageField))]
internal class Field
{
    [DataMember(Order=1)]
    public string Value { get; set; }
}

[DataContract]
internal class LanguageField : Field
{

}

[DataContract]
[KnownType(typeof(BackButton))]
[KnownType(typeof(CancelButton))]
[KnownType(typeof(NextButton))]
internal class Button
{

}

[DataContract]
internal class BackButton : Button
{

}

[DataContract]
internal class CancelButton : Button
{

}

[DataContract]
internal class NextButton : Button
{

}

Where exactly am I going wrong? Is there a specific way that you need to declare a contract for an inherited item?

Upvotes: 2

Views: 473

Answers (1)

Avinash Jain
Avinash Jain

Reputation: 7616

You should add DataContract name to Button as shown below

[DataContract(Name="ThisIsButton")]
[KnownType(typeof(BackButton))]
[KnownType(typeof(CancelButton))]
[KnownType(typeof(NextButton))]
internal class Button
{

}

And then add itype to you xml

  <Buttons>
    <CancelButton itype="ThisIsButton"/>
    <BackButton itype="ThisIsButton"/>
    <NextButton itype="ThisIsButton"/>
  </Buttons>

Upvotes: 1

Related Questions