Как я могу десериализовать XML, когда я знаю только класс предка? - PullRequest
5 голосов
/ 24 февраля 2011

Давайте предположим, что я хочу десериализовать это (я удалил пространства имен, чтобы упростить задачу):

<TextField>
  <Caption>Location</Caption>
  <Name>Location</Name>
</TextField>

TextField наследуется от FormField, поэтому в моем определении класса FormField выглядит примерно так:

[KnownType(typeof(TextField))]
[DataContract(Name = "FormField"]
public abstract class FormField
{
    [DataMember]
    public string Name { get; set; }
}

Класс TextField выглядит следующим образом:

[DataContract(Name = "TextField")]
public class TextField : FormField
{
    [DataMember]
    public string Caption { get; set; }
}

Я попытался десериализовать, используя это:

internal static FormField Deserialize(string xml)
{
    var serializer = new DataContractSerializer(typeof(FormField)});
    using (var backing = new StringReader(xml))
    {
        using (var reader = new XmlTextReader(backing))
        {
            return serializer.ReadObject(reader) as FormField;
        }
    }
}

Я получаю исключение SerializationException: «Ожидается элемент« FormField »... "

Ответы [ 2 ]

0 голосов
/ 25 февраля 2011

Чтобы решить мою проблему, я добавил контейнерный узел в XML, чтобы он выглядел так:

<FormFieldContainer>
    <TextField>   
        <Caption>Location</Caption>
        <Name>Location</Name>
    </TextField>
</FormFieldContainer>

Я создал этот класс:

[DataContract(Name = "FormFieldContainer")]
internal class FormFieldContainer
{
    [DataMember]
    internal FormField FormField { get; set; }
}

И мой метод десериализациивыглядит так:

    internal static FormField Deserialize(string xml)
    {
        var serializer = new DataContractSerializer(typeof(FormFieldContainer));
        using (var backing = new StringReader(xml))
        {
            using (var reader = new XmlTextReader(backing))
            {
                return ((FormFieldContainer)serializer.ReadObject(reader)).FormField;
            }
        }
    }

Если у кого-то есть лучшее решение, поделитесь им:)

0 голосов
/ 24 февраля 2011

Разве ваша модель не должна выглядеть так?

public abstract class TextField: FormField
{
    [DataMember]
    public string Name { get; set; }
}

просто удар, на самом деле я только что начал странным образом погружаться в список материалов DataContractSerializer ночью.

...