toddmo
toddmo

Reputation: 22436

Property of a List<T> Not Deserialized

The property FilePattern does not get deserialized from the xml:

<Parser FilePattern='*'/>
[Serializable(), XmlRoot("Parser")]
public class Parser : List<System.DateTime>
{

    private string _FilePattern;
    [XmlAttribute()]
    public string FilePattern {
        get { return _FilePattern; }
        set { _FilePattern = value; }
    }

}
private void ParserTest()
{
    Parser Parser = Serialization.Deserialize("<Parser FilePattern='*'/>", typeof(Parser));
    // Here, Parser.FilePattern is null
}

Parser is just a class. How can I make it populate the FilePattern property?

Upvotes: 1

Views: 381

Answers (2)

toddmo
toddmo

Reputation: 22436

Sometimes you just want to do what you just want to do; the Framework be damned.

Here's a first draft of a routine that worked for me in my situation. As it evolves over time I will update my answer.

I have located this in my Serialization helper module alongside my other Deserialize methods for "normal" classes.

Basically, what it does is a normal deserialization, to let the xml deserializer to all the heavy lifting, then it populates the newly deserialized object with the properties of the xml element.

Like I say, it's a draft, but Marc Gravell said it was a lot of work, so I just had to do it (to make it not a lot of work for you)!

/// <summary>
/// Overcome limitation of xml serializer 
/// that it can't deserialize properties of classes 
/// that inherit from IEnumerable
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="Xml"></param>
/// <returns></returns>
/// <remarks></remarks>
public T Deserialize<T>(string Xml) where T : IEnumerable
{
    T functionReturnValue = default(T);
    //let the xml serializer do the rest of the work
    functionReturnValue = Deserialize(Xml, typeof(T));

    //copy over the additional properties
    using (XmlReader XmlReader = XmlTextReader.Create(new StringReader(Xml), new XmlReaderSettings {ValidationType = ValidationType.None,XmlResolver = null})) {
        XmlReader.MoveToContent();
        for (int Index = 0; Index <= XmlReader.AttributeCount - 1; Index++) {
            XmlReader.MoveToAttribute(Index);
            typeof(T).GetProperty(XmlReader.LocalName).SetValue(Deserialize(), XmlReader.Value, null);
        }
    }
    return functionReturnValue;
}

public object Deserialize(string Xml, Type Type)
{
    object functionReturnValue = null;
    functionReturnValue = null;
    if (Xml == string.Empty) {
        return null;
    }
    _Serializer = new XmlSerializer(Type);
    StringReader StringReader = new StringReader(Xml);
    functionReturnValue = Serializer.Deserialize(StringReader);
    if (functionReturnValue is IDeserializationEvents) {
        ((IDeserializationEvents)functionReturnValue).DeserializationComplete();
    }
    return functionReturnValue;
}

Upvotes: 1

Brad
Brad

Reputation: 4192

The XmlSerializer has special behavior when it comes to IEnumerable types, and so you may be witnessing some kind of conflict with that. You could consider doing something like the following that mimics the behavior you want without actually making your type a list:

[XmlRoot("Parser")]
public class Parser
{
    public Parser()
    {
      this.Values = new List<DateTime>();
    }

    [XmlAttribute]
    public string Attrib { get; set; }

    [XmlElement("dateTime")]
    public List<DateTime> Values { get; private set; }
}

Upvotes: 2

Related Questions