/// <summary> /// Parses an instance of the specified type from the specified stream /// </summary> public object Parse(System.Xml.XmlReader s, Type useType, Type currentInteractionType, XmlIts1FormatterParseResult resultContext) { ConstructorInfo ci = useType.GetConstructor(Type.EmptyTypes); if(ci == null) throw new InvalidOperationException(String.Format("Cannot create an instance of type '{0}' as it defines no default constructor", useType.FullName)); // Create the instance object instance = ci.Invoke(null); PropertyInfo[] properties = useType.GetProperties(BindingFlags.Public | BindingFlags.Instance); // Move the reader to the first attribute if (s.MoveToFirstAttribute()) { // Now we read the attributes and match with the properties do { #if WINDOWS_PHONE PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0); #else PropertyInfo pi = Array.Find<PropertyInfo>(properties, o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0); #endif // Can we set the PI? if (s.LocalName == "ITSVersion" && s.Value != "XML_1.0") throw new System.InvalidOperationException(System.String.Format("This formatter can only parse XML_1.0 structures. This structure claims to be '{0}'.", s.Value)); else if (s.Prefix == "xmlns" || s.LocalName == "xmlns" || s.LocalName == "ITSVersion" || s.NamespaceURI == XmlIts1Formatter.NS_XSI) continue; else if (pi == null) { resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, String.Format("@{0}", s.LocalName), s.NamespaceURI, s.ToString(), null)); continue; } var paList = pi.GetCustomAttributes(typeof(PropertyAttribute), true); // property attributes // VAlidate list of PA if(paList == null || paList.Length != 1) { resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Warning, String.Format("Invalid number of PropertyAttributes on property '{0}', ignoring", pi.Name), s.ToString(), null)); continue; // not a property to be parsed } if (pi.GetSetMethod() == null) { if (!Util.ToWireFormat(pi.GetValue(instance, null)).Equals(s.Value)) resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, pi.GetValue(instance, null).ToString(), true, s.ToString())); } else if (!String.IsNullOrEmpty((paList[0] as PropertyAttribute).FixedValue)) { if (!(paList[0] as PropertyAttribute).FixedValue.Equals(s.Value)) { resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, (paList[0] as PropertyAttribute).FixedValue, false, s.ToString())); pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null); } } else pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null); } while (s.MoveToNextAttribute()); s.MoveToElement(); } // Nil? // BUG: Fixed, xsi:nil may also have a null-flavor String nil = s.GetAttribute("nil", XmlIts1Formatter.NS_XSI); if (!String.IsNullOrEmpty(nil) && Convert.ToBoolean(nil)) return instance; // Is reader at an empty element if (s.IsEmptyElement) return instance; // Read content string currentElementName = s.LocalName, lastElementRead = s.LocalName; while(true) { // End of stream or item not read if (lastElementRead == s.LocalName && !s.Read()) break; lastElementRead = s.LocalName; // Element is end element and matches the starting element namd if (s.NodeType == System.Xml.XmlNodeType.EndElement && s.LocalName == currentElementName) break; // Element is an end element //else if (s.NodeType == System.Xml.XmlNodeType.EndElement) // currentDepth--; // Element is a start element else if (s.NodeType == System.Xml.XmlNodeType.Element) { // Get the element choice property #if WINDOWS_PHONE PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(a => a is PropertyAttribute && (a as PropertyAttribute).Name == s.LocalName && ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0); #else PropertyInfo pi = Array.Find(properties, o => o.GetCustomAttributes(true).Count(a => a is PropertyAttribute && (a as PropertyAttribute).Name == s.LocalName && ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0); #endif if (pi == null) { resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, s.LocalName, s.NamespaceURI, s.ToString(), null)); continue; } // Get the property attribute that defined the choice #if WINDOWS_PHONE PropertyAttribute pa = pi.GetCustomAttributes(true).Find(p => p is PropertyAttribute && (p as PropertyAttribute).Name == s.LocalName && ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute; #else PropertyAttribute pa = Array.Find(pi.GetCustomAttributes(true), p => p is PropertyAttribute && (p as PropertyAttribute).Name == s.LocalName && ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute; #endif // Can we set the PI? if (pi == null || !pi.CanWrite) continue; // Now time to set the PI if (String.IsNullOrEmpty(s.GetAttribute("specializationType")) && s is MARC.Everest.Xml.XmlStateReader && (this.Host.Settings & SettingsType.AllowFlavorImposing) == SettingsType.AllowFlavorImposing) (s as MARC.Everest.Xml.XmlStateReader).AddFakeAttribute("specializationType", pa.ImposeFlavorId); // Cannot deserialize this if (pa.Type == null && pi.PropertyType == typeof(System.Object)) resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, pi.Name, pa.NamespaceUri, s.ToString(), null)); // Simple deserialization if PA type has IGraphable or PI type has IGraphable and PA type not specified else if (pi.GetSetMethod() != null && (pa.Type != null && pa.Type.GetInterface(typeof(IGraphable).FullName, false) != null) || (pa.Type == null && pi.PropertyType.GetInterface(typeof(IGraphable).FullName, false) != null)) { object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext); if (!String.IsNullOrEmpty(pa.FixedValue) && !pa.FixedValue.Equals(Util.ToWireFormat(tempFormat)) && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable) resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(Util.ToWireFormat(tempFormat), pa.FixedValue, s.ToString())); pi.SetValue(instance, Util.FromWireFormat(tempFormat, pa.Type ?? pi.PropertyType), null); } // Call an Add method on a collection type else if (pi.PropertyType.GetMethod("Add") != null) // Collection type pi.PropertyType.GetMethod("Add").Invoke(pi.GetValue(instance, null), new object[] { Util.FromWireFormat(Host.ParseObject(s, pi.PropertyType.GetGenericArguments()[0], currentInteractionType, resultContext), pi.PropertyType.GetGenericArguments()[0]) }); // Call the ParseXML custom function on object else if (pi.GetSetMethod() != null && pi.PropertyType.GetMethod("ParseXml", BindingFlags.Public | BindingFlags.Static) != null) pi.SetValue(instance, pi.PropertyType.GetMethod("ParseXml").Invoke(instance, new object[] { s }), null); // Property type is a simple string else if (pi.GetSetMethod() != null && pi.PropertyType == typeof(string)) // Read content... pi.SetValue(instance, Util.FromWireFormat(s.ReadInnerXml(), typeof(String)), null); // No Set method is used, fixed value? else { object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext); if (tempFormat.ToString() != pi.GetValue(instance, null).ToString() && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable) resultContext.AddResultDetail(new MARC.Everest.Connectors.FixedValueMisMatchedResultDetail(tempFormat.ToString(), pi.GetValue(instance, null).ToString(), s.ToString())); } } } return instance; }
/// <summary> /// Parses an instance of the specified type from the specified stream /// </summary> public object Parse(System.Xml.XmlReader s, Type useType, Type currentInteractionType, XmlIts1FormatterParseResult resultContext) { ConstructorInfo ci = useType.GetConstructor(Type.EmptyTypes); if (ci == null) { throw new InvalidOperationException(String.Format("Cannot create an instance of type '{0}' as it defines no default constructor", useType.FullName)); } // Create the instance object instance = ci.Invoke(null); PropertyInfo[] properties = useType.GetProperties(BindingFlags.Public | BindingFlags.Instance); // Move the reader to the first attribute if (s.MoveToFirstAttribute()) { // Now we read the attributes and match with the properties do { #if WINDOWS_PHONE PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0); #else PropertyInfo pi = Array.Find <PropertyInfo>(properties, o => o.GetCustomAttributes(true).Count(pa => pa is PropertyAttribute && (pa as PropertyAttribute).Name == s.LocalName) > 0); #endif // Can we set the PI? if (s.LocalName == "ITSVersion" && s.Value != "XML_1.0") { throw new System.InvalidOperationException(System.String.Format("This formatter can only parse XML_1.0 structures. This structure claims to be '{0}'.", s.Value)); } else if (s.Prefix == "xmlns" || s.LocalName == "xmlns" || s.LocalName == "ITSVersion" || s.NamespaceURI == XmlIts1Formatter.NS_XSI) { continue; } else if (pi == null) { resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, String.Format("@{0}", s.LocalName), s.NamespaceURI, s.ToString(), null)); continue; } var paList = pi.GetCustomAttributes(typeof(PropertyAttribute), true); // property attributes // VAlidate list of PA if (paList == null || paList.Length != 1) { resultContext.AddResultDetail(new ResultDetail(ResultDetailType.Warning, String.Format("Invalid number of PropertyAttributes on property '{0}', ignoring", pi.Name), s.ToString(), null)); continue; // not a property to be parsed } if (pi.GetSetMethod() == null) { if (!Util.ToWireFormat(pi.GetValue(instance, null)).Equals(s.Value)) { resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, pi.GetValue(instance, null).ToString(), true, s.ToString())); } } else if (!String.IsNullOrEmpty((paList[0] as PropertyAttribute).FixedValue)) { if (!(paList[0] as PropertyAttribute).FixedValue.Equals(s.Value)) { resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(s.Value, (paList[0] as PropertyAttribute).FixedValue, false, s.ToString())); pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null); } } else { pi.SetValue(instance, Util.FromWireFormat(s.Value, pi.PropertyType), null); } }while (s.MoveToNextAttribute()); s.MoveToElement(); } // Nil? // BUG: Fixed, xsi:nil may also have a null-flavor String nil = s.GetAttribute("nil", XmlIts1Formatter.NS_XSI); if (!String.IsNullOrEmpty(nil) && Convert.ToBoolean(nil)) { return(instance); } // Is reader at an empty element if (s.IsEmptyElement) { return(instance); } // Read content string currentElementName = s.LocalName, lastElementRead = s.LocalName; while (true) { // End of stream or item not read if (lastElementRead == s.LocalName && !s.Read()) { break; } lastElementRead = s.LocalName; // Element is end element and matches the starting element namd if (s.NodeType == System.Xml.XmlNodeType.EndElement && s.LocalName == currentElementName) { break; } // Element is an end element //else if (s.NodeType == System.Xml.XmlNodeType.EndElement) // currentDepth--; // Element is a start element else if (s.NodeType == System.Xml.XmlNodeType.Element) { // Get the element choice property #if WINDOWS_PHONE PropertyInfo pi = properties.Find(o => o.GetCustomAttributes(true).Count(a => a is PropertyAttribute && (a as PropertyAttribute).Name == s.LocalName && ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0); #else PropertyInfo pi = Array.Find(properties, o => o.GetCustomAttributes(true).Count(a => a is PropertyAttribute && (a as PropertyAttribute).Name == s.LocalName && ((a as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) > 0); #endif if (pi == null) { resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, s.LocalName, s.NamespaceURI, s.ToString(), null)); continue; } // Get the property attribute that defined the choice #if WINDOWS_PHONE PropertyAttribute pa = pi.GetCustomAttributes(true).Find(p => p is PropertyAttribute && (p as PropertyAttribute).Name == s.LocalName && ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute; #else PropertyAttribute pa = Array.Find(pi.GetCustomAttributes(true), p => p is PropertyAttribute && (p as PropertyAttribute).Name == s.LocalName && ((p as PropertyAttribute).InteractionOwner ?? currentInteractionType) == currentInteractionType) as PropertyAttribute; #endif // Can we set the PI? if (pi == null || !pi.CanWrite) { continue; } // Now time to set the PI if (String.IsNullOrEmpty(s.GetAttribute("specializationType")) && s is MARC.Everest.Xml.XmlStateReader && (this.Host.Settings & SettingsType.AllowFlavorImposing) == SettingsType.AllowFlavorImposing) { (s as MARC.Everest.Xml.XmlStateReader).AddFakeAttribute("specializationType", pa.ImposeFlavorId); } // Cannot deserialize this if (pa.Type == null && pi.PropertyType == typeof(System.Object)) { resultContext.AddResultDetail(new NotImplementedElementResultDetail(ResultDetailType.Warning, pi.Name, pa.NamespaceUri, s.ToString(), null)); } // Simple deserialization if PA type has IGraphable or PI type has IGraphable and PA type not specified else if (pi.GetSetMethod() != null && (pa.Type != null && pa.Type.GetInterface(typeof(IGraphable).FullName, false) != null) || (pa.Type == null && pi.PropertyType.GetInterface(typeof(IGraphable).FullName, false) != null)) { object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext); if (!String.IsNullOrEmpty(pa.FixedValue) && !pa.FixedValue.Equals(Util.ToWireFormat(tempFormat)) && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable) { resultContext.AddResultDetail(new FixedValueMisMatchedResultDetail(Util.ToWireFormat(tempFormat), pa.FixedValue, s.ToString())); } pi.SetValue(instance, Util.FromWireFormat(tempFormat, pa.Type ?? pi.PropertyType), null); } // Call an Add method on a collection type else if (pi.PropertyType.GetMethod("Add") != null) // Collection type { pi.PropertyType.GetMethod("Add").Invoke(pi.GetValue(instance, null), new object[] { Util.FromWireFormat(Host.ParseObject(s, pi.PropertyType.GetGenericArguments()[0], currentInteractionType, resultContext), pi.PropertyType.GetGenericArguments()[0]) }); } // Call the ParseXML custom function on object else if (pi.GetSetMethod() != null && pi.PropertyType.GetMethod("ParseXml", BindingFlags.Public | BindingFlags.Static) != null) { pi.SetValue(instance, pi.PropertyType.GetMethod("ParseXml").Invoke(instance, new object[] { s }), null); } // Property type is a simple string else if (pi.GetSetMethod() != null && pi.PropertyType == typeof(string)) // Read content... { pi.SetValue(instance, Util.FromWireFormat(s.ReadInnerXml(), typeof(String)), null); } // No Set method is used, fixed value? else { object tempFormat = Host.ParseObject(s, pa.Type ?? pi.PropertyType, currentInteractionType, resultContext); if (tempFormat.ToString() != pi.GetValue(instance, null).ToString() && pa.PropertyType != PropertyAttribute.AttributeAttributeType.Traversable) { resultContext.AddResultDetail(new MARC.Everest.Connectors.FixedValueMisMatchedResultDetail(tempFormat.ToString(), pi.GetValue(instance, null).ToString(), s.ToString())); } } } } return(instance); }