/// <summary> /// Reads a single child xml element from the specified element as a given type, constructing the child programatically /// </summary> /// <remarks> /// This is useful for reading a (singular) child element of an xml element into an object that implements /// <see cref="IXmlReadable"/>. This also gives you a way to create the instance used for the child object /// programatically. /// /// If your child class does not require special construction logic and has a default constructor, you can use <see cref="ReadChildXml{T}(XmlElement, string)"/> instead. /// </remarks> /// <seealso cref="WriteChildXml{T}(XmlElement, string, T)"/> /// <seealso cref="ReadChildXml{T}(XmlElement, string)"/> /// <example> /// <code><![CDATA[ /// public class MyChild : IXmlReadable { /// public static MyChild CreateFromXml (XmlElement element) { /// switch (element.GetAttribute("type")) { /// case "typea": return new MyChildTypeA(); /// case "typeb": return new MyChildTypeB(); /// default: return null; /// } /// } /// /// // implement IXmlReadable (usually as virtual methods for derived classes to override) /// } /// /// public class MyChildTypeA : MyChild { /// } /// /// public class MyChildTypeB : MyChild { /// } /// /// public class MyParent : IXmlReadable { /// /// public MyChild Child { get; set; } /// /// public void WriteXml (XmlElement element) { /// element.WriteChildXml("mychild", this.Child); /// } /// /// public void ReadXml (XmlElement element) { /// this.Child = element.ReadChildXml<MyChild>("mychild", MyChild.CreateFromXml); /// } /// } /// ]]></code> /// </example> /// <typeparam name="T">Type of child to read (must be <see cref="IXmlReadable"/>)</typeparam> /// <param name="element">Element to read the child node from</param> /// <param name="childElementName">Name of the child element to read</param> /// <param name="create">Delegate to create the child object instance if needed</param> /// <returns>A new instance of the specified type if the child element exists with properties read from xml, otherwise null</returns> public static T ReadChildXml <T> (this XmlElement element, string childElementName, CreateFromXml <T> create) where T : IXmlReadable { var childElement = element.SelectSingleNode(childElementName) as XmlElement; if (childElement == null) { return(default(T)); } var child = create(childElement); if (!EqualityComparer <T> .Default.Equals(child, default(T))) { child.ReadXml(childElement); } return(child); }
/// <summary> /// Reads child elements into a list, constructing the child objects programatically /// </summary> /// <example> /// <code><![CDATA[ /// public class MyChild : IXmlReadable { /// public static MyChild CreateFromXml (XmlElement element) { /// switch (element.GetAttribute("type")) { /// case "typea": return new MyChildTypeA(); /// case "typeb": return new MyChildTypeB(); /// default: return null; /// } /// } /// /// // implement IXmlReadable (usually as virtual methods for derived classes to override) /// } /// /// public class MyChildTypeA : MyChild { /// } /// /// public class MyChildTypeB : MyChild { /// } /// /// public class MyParent : IXmlReadable { /// /// public List<MyChild> Children { get; set; } /// /// public void WriteXml (XmlElement element) { /// element.WriteChildListXml<MyChild>(this.Children, "mychild", "children"); /// } /// /// public void ReadXml (XmlElement element) { /// this.Children = new List<MyChild>(); /// element.ReadChildListXml<MyChild>(this.Children, MyChild.CreateFromXml, "mychild", "children"); /// } /// } /// ]]></code> /// </example> /// <typeparam name="T">Type of each child object</typeparam> /// <param name="element">Element to read the child elements from</param> /// <param name="list">List to add the child elements to</param> /// <param name="create">Delegate to create the child object to add to the list</param> /// <param name="childElement">Name of the child elements to read</param> /// <param name="listElement">If specified, the list element where the child elements are to be read from, or null to read the child elements directly from the <paramref name="element"/></param> public static void ReadChildListXml <T> (this XmlElement element, IList <T> list, CreateFromXml <T> create, string childElement, string listElement = null) where T : IXmlReadable { XmlNodeList childNodes = null; if (listElement != null) { var listNode = element.SelectSingleNode(listElement); if (listNode != null) { childNodes = listNode.SelectNodes(childElement); } } else { childNodes = element.SelectNodes(childElement); } if (childNodes != null) { list.Clear(); foreach (XmlElement childNode in childNodes) { var item = create(childNode); if (!EqualityComparer <T> .Default.Equals(item, default(T))) { item.ReadXml(childNode); list.Add(item); } } } }
/// <summary> /// Reads child elements into a list, constructing the child objects programatically /// </summary> /// <example> /// <code><![CDATA[ /// public class MyChild : IXmlReadable { /// public static MyChild CreateFromXml (XmlElement element) { /// switch (element.GetAttribute("type")) { /// case "typea": return new MyChildTypeA(); /// case "typeb": return new MyChildTypeB(); /// default: return null; /// } /// } /// /// // implement IXmlReadable (usually as virtual methods for derived classes to override) /// } /// /// public class MyChildTypeA : MyChild { /// } /// /// public class MyChildTypeB : MyChild { /// } /// /// public class MyParent : IXmlReadable { /// /// public List<MyChild> Children { get; set; } /// /// public void WriteXml (XmlElement element) { /// element.WriteChildListXml<MyChild>(this.Children, "mychild", "children"); /// } /// /// public void ReadXml (XmlElement element) { /// this.Children = new List<MyChild>(); /// element.ReadChildListXml<MyChild>(this.Children, MyChild.CreateFromXml, "mychild", "children"); /// } /// } /// ]]></code> /// </example> /// <typeparam name="T">Type of each child object</typeparam> /// <param name="element">Element to read the child elements from</param> /// <param name="list">List to add the child elements to</param> /// <param name="create">Delegate to create the child object to add to the list</param> /// <param name="childElement">Name of the child elements to read</param> /// <param name="listElement">If specified, the list element where the child elements are to be read from, or null to read the child elements directly from the <paramref name="element"/></param> public static void ReadChildListXml <T>(this XmlElement element, IList <T> list, CreateFromXml <T> create, string childElement, string listElement = null) where T : IXmlReadable { XmlNodeList childNodes = null; if (listElement != null) { var listNode = element.SelectSingleNode(listElement); if (listNode != null) { childNodes = listNode.SelectNodes(childElement); } } else { childNodes = element.SelectNodes(childElement); } if (childNodes != null) { if (!list.IsReadOnly) { list.Clear(); } else { for (int i = 0; i < list.Count; i++) { list[i] = default(T); } } int index = 0; foreach (XmlElement childNode in childNodes) { var item = create(childNode); if (!EqualityComparer <T> .Default.Equals(item, default(T))) { item.ReadXml(childNode); if (list.IsReadOnly) { if (index < list.Count) { list[index++] = item; } else { break; } } else { list.Add(item); } } } } }