简体   繁体   中英

XML Deserialization: Store objects as separate XMLs, or as one?

I see a lot of examples online where we have a class with a static factory-model deserializer, like below. Couple of questions on this model:

  1. Do these examples really assume that we store every person instance as a separate XML file?
  2. Would not a much more common case be that my XML has a root element called <Persons> , and then many sets of <Person> follows?
  3. In this case, the Deserialization method below would not really work right? It seems to be built to read an XML with only one level

     class Person { public Name {get; set;} public Age {get; set;} public static Skill Deserialize(string path) { using (var memoryStream = new StreamReader(path)) { var serializer = new XmlSerializer(typeof(Skill)); var local = (Skill)serializer.Deserialize(memoryStream); local.PostCreateLogic(); return local; } } private void PostCreateLogic() { Age = Age + 10; } } 

Thanks for helping me understand this better. There must be something I am not seeing right, as almost every example deals with deserialization on an object by object basis...

My solution follows below.

I have found some examples out there that stores many Persons, Cars, Skills, or what your object might be, in one XML file. All you do is put the factory-model static method in a class you can call SkillCollection (for example). Please see my example below:

[XmlRootAttribute("Skills")]
public class SkillCollection
{
    //Not neccessary to use attributes if the Property name matches the XML element name
    [XmlElement(ElementName = "Fire")]
    public Skill Fire { get; [UsedImplicitly] set; }

    [XmlElement(ElementName = "Ice")]
    public Skill Ice { get; [UsedImplicitly] set; }

    //If all the skills were named the same I could deserialize into an array, as shown below
    //But then I would have no way to access each skill, in my code
    //[XmlArray]
    //public Skill[] SkillCollection { get; set; }

    //Factory-Model to create an instance of SkillCollection class
    public static object XmlSerializer_Deserialize(string path, Type toType)
    {
        var deserializer = new XmlSerializer(toType);
        using (TextReader reader = new StreamReader(path))
        {
            object s2 = deserializer.Deserialize(reader);
            if (s2 == null)
                Console.WriteLine(@"  Deserialized object is null");
            else
                Console.WriteLine(@"  Deserialized type: {0}", s2.GetType());
            return s2;
        }
    }
}

And Skill class:

public class Skill
{
    [XmlElement(ElementName = "Cast")]
    public int Cast { get; set; }

    [XmlElement(ElementName = "ReCast")]
    public int ReCast { get; set; }

    [XmlElement(ElementName = "MPCost")]
    public int MpCost { get; set; }
}

To use the method: (SkillCollection)SkillCollection.XmlSerializer_Deserialize(Path.Combine(path, "Skills.xml"), typeof(SkillCollection)); and store that in a property that you can access throughout your application...

Also, don't forget to use [XmlIgnore] above any properties in Skill and SkillCollection that are not defined in the XML. It is a requirement for XmlSerializer that the XML elements matches all the public properties in the class you are attempting to deserialize to.

As a side-note, the XML does not need to be sorted alphabetically, which happens to be a requirement if you use DataContractSerializer instead.

Hope this helps future visitors. Any questions, please let me know.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM