/// <summary> /// Loads the specified id. /// </summary> /// <typeparam name="TDocType">The type of the doc type.</typeparam> /// <param name="id">The id.</param> /// <returns></returns> /// <exception cref="umbraco.Linq.Core.DocTypeMissMatchException">If the type of the parent does not match the provided type</exception> /// <exception cref="System.ArgumentException">No node found matching the provided ID for the parent</exception> /// <exception cref="System.ObjectDisposedException">When the data provider has been disposed of</exception> public override TDocType Load <TDocType>(int id) { CheckDisposed(); var parentXml = this.Xml.Descendants().SingleOrDefault(d => d.Attribute("isDoc") != null && (int)d.Attribute("id") == id); if (!ReflectionAssistance.CompareByAlias(typeof(TDocType), parentXml)) { throw new DocTypeMissMatchException(parentXml.Name.LocalName, ReflectionAssistance.GetUmbracoInfoAttribute(typeof(TDocType)).Alias); } if (parentXml == null) //really shouldn't happen! { throw new ArgumentException("Parent ID \"" + id + "\" cannot be found in the loaded XML. Ensure that the umbracoDataContext is being disposed of once it is no longer needed"); } var parent = new TDocType(); this.LoadFromXml(parentXml, parent); return(parent); }
/// <summary> /// Gets the enumerator. /// </summary> /// <returns></returns> public override IEnumerator <TDocTypeBase> GetEnumerator() { if (this._nodes == null) { this._nodes = new List <TDocTypeBase>(); var rawNodes = this._provider.Xml.Descendants().Where(x => ReflectionAssistance.CompareByAlias(typeof(TDocTypeBase), x)); lock (lockObject) { foreach (XElement n in rawNodes) { var dt = new TDocTypeBase(); this._provider.LoadFromXml(n, dt); dt.IsDirty = false; dt.Provider = this._provider; this._nodes.Add(dt); } } } return(this._nodes.GetEnumerator()); }
/// <summary> /// Loads from XML. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="xml">The XML.</param> /// <param name="node">The node.</param> public void LoadFromXml <T>(XElement xml, T node) where T : DocTypeBase { if (!ReflectionAssistance.CompareByAlias(node.GetType(), xml)) { throw new DocTypeMissMatchException(xml.Name.LocalName, ReflectionAssistance.GetUmbracoInfoAttribute(node.GetType()).Alias); } node.Id = (int)xml.Attribute("id"); node.ParentNodeId = (int)xml.Attribute("parentID"); node.NodeName = (string)xml.Attribute("nodeName"); node.Version = (string)xml.Attribute("version"); node.CreateDate = (DateTime)xml.Attribute("createDate"); node.SortOrder = (int)xml.Attribute("sortOrder"); node.UpdateDate = (DateTime)xml.Attribute("updateDate"); node.CreatorID = (int)xml.Attribute("creatorID"); node.CreatorName = (string)xml.Attribute("creatorName"); node.WriterID = (int)xml.Attribute("writerID"); node.WriterName = (string)xml.Attribute("writerName"); node.Level = (int)xml.Attribute("level"); node.TemplateId = (int)xml.Attribute("template"); var properties = node.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance).Where(p => p.GetCustomAttributes(typeof(PropertyAttribute), true).Count() > 0); foreach (var p in properties) { var attr = ReflectionAssistance.GetUmbracoInfoAttribute(p); XElement propertyXml = xml.Element(Casing.SafeAlias(attr.Alias)); string data = null; //if the XML doesn't contain the property it means that the node hasn't been re-published with the property //so then we'll leave the data at null, otherwise let's grab it //Check if the propertyXml and propertyXml.FirstNode aren't null. If they are we don't need to set the value. if (propertyXml != null && propertyXml.FirstNode != null) { //If the FirstNode is an XElement it means the property contains inner xml and we should return it. Otherwise just return the normal value. if (propertyXml.FirstNode is XElement) { var reader = propertyXml.CreateReader(); reader.MoveToContent(); data = reader.ReadInnerXml(); } else { data = propertyXml.Value; } } if (p.PropertyType.IsValueType && p.PropertyType.GetGenericArguments().Length > 0 && typeof(Nullable <>).IsAssignableFrom(p.PropertyType.GetGenericTypeDefinition())) { if (string.IsNullOrEmpty(data)) { //non-mandatory structs which have no value will be null try { p.SetValue(node, null, null); } catch (FormatException ex) { throw new FormatException( string.Format("Unable to cast '{0}' to the appropriate type ({1}) for node `{2}`. The alias of the property being parsed is {3}. Refer to inner exception for more details", data, p.PropertyType.FullName, node.Id, attr.Alias), ex); } } else { //non-mandatory structs which do have a value have to be cast based on the type of their Nullable<T>, found from the first (well, only) GenericArgument try { p.SetValue(node, Convert.ChangeType(data, p.PropertyType.GetGenericArguments()[0]), null); } catch (FormatException ex) { throw new FormatException( string.Format("Unable to cast '{0}' to the appropriate type ({1}) for node `{2}`. The alias of the property being parsed is {3}. Refer to inner exception for more details", data, p.PropertyType.FullName, node.Id, attr.Alias), ex); } } } else { // TODO: Address how Convert.ChangeType works in globalisation try { p.SetValue(node, Convert.ChangeType(data, p.PropertyType), null); } catch (FormatException ex) { throw new FormatException( string.Format("Unable to cast '{0}' to the appropriate type ({1}) for node `{2}`. The alias of the property being parsed is {3}. Refer to inner exception for more details", data, p.PropertyType.FullName, node.Id, attr.Alias), ex); } } } }