XObject GenerateReportProperty(ReportBaseProperty reportBaseProperty, object propertyValue, int maxDepth) { if (propertyValue == null) { return(null); } if (reportBaseProperty is ReportCollectionProperty) { // ------------------- // Item collection ReportCollectionProperty reportProperty = (ReportCollectionProperty)reportBaseProperty; ReportElementProperty reportItemProperty = reportProperty.ItemProperty as ReportElementProperty; if (reportItemProperty == null) { throw new InvalidOperationException("Missing item property for " + reportBaseProperty.Name); } List <XElement> itemElements = new List <XElement>(); foreach (object item in (System.Collections.IEnumerable)propertyValue) { XElement itemElement = (XElement)GenerateReportProperty(reportItemProperty, item, maxDepth); if (itemElement != null) { itemElements.Add(itemElement); } } if (itemElements.Count == 0) { return(null); } if (!string.IsNullOrEmpty(reportProperty.OrderBy)) { string[] attributeNames = reportProperty.OrderBy.Split(','); IEnumerable <XElement> enumeration = itemElements; // Build up the sorting criteria foreach (string attributeName in attributeNames.Reverse()) { enumeration = enumeration.OrderBy( delegate(XElement element) { XAttribute attribute = element.Attribute(attributeName); if (attribute == null) { return(null); } return(attribute.Value); } ); } // Perform the sort itemElements = enumeration.ToList(); } return(new XElement(reportProperty.Name, itemElements.ToArray())); } ReportType forcedReportType = reportBaseProperty.UseToString ? UseToStringReportType : null; if (reportBaseProperty is ReportAttributeProperty) { // ------------------- // Attribute ReportAttributeProperty reportProperty = (ReportAttributeProperty)reportBaseProperty; XElement propertyElement = GenerateReport(reportBaseProperty.Name, propertyValue, forcedReportType, maxDepth); if (propertyElement == null) { return(null); } if (propertyElement.HasElements || propertyElement.HasAttributes) { throw new InvalidOperationException("The type " + propertyValue.GetType().FullName + " cannot be used as an attribute"); } return(new XAttribute(reportProperty.Name, propertyElement.Value)); } if (reportBaseProperty is ReportElementProperty) { // ------------------- // Element ReportElementProperty reportProperty = (ReportElementProperty)reportBaseProperty; if (reportProperty.AsEmbeddedXml) { // Embedded XML if (propertyValue != null && !(propertyValue is string)) { throw new InvalidOperationException("AsEmbeddedXml used with a non-string value"); } XElement parsed = null; string propertyXml = (string)propertyValue; if (propertyXml == null || propertyXml.Trim().Length == 0) { return(null); } try { parsed = XElement.Load(new StringReader((string)propertyValue)); } catch (Exception ex) { parsed = new XElement("Error", ex.Message); } return(new XElement(reportProperty.Name, parsed, new XAttribute("EmbeddedXml", true))); } // Regular element XElement propertyElement = GenerateReport(reportBaseProperty.Name, propertyValue, forcedReportType, maxDepth); if (propertyElement == null) { return(null); } return(propertyElement); } throw new InvalidOperationException(); }
XElement GenerateReport(string elementName, object value, ReportType forcedReportType, int maxDepth) { maxDepth -= 1; if (value == null) { return(null); } Type type = value.GetType(); ReportType reportType = forcedReportType; if (reportType == null) { TypesByName.TryGetValue(type.FullName, out reportType); } if (reportType == null) { TypesByName.TryGetValue(type.Name, out reportType); } if (reportType == null && type.IsEnum) { reportType = UseToStringReportType; } if (reportType == null) { // Check for MatchChildClasses for (Type baseClass = type.BaseType; baseClass != null; baseClass = baseClass.BaseType) { if (TypesByName.TryGetValue(baseClass.FullName, out reportType)) { if (!reportType.MatchChildClasses) { reportType = null; } } if (reportType != null) { break; } if (TypesByName.TryGetValue(baseClass.Name, out reportType)) { if (!reportType.MatchChildClasses) { reportType = null; } } if (reportType != null) { break; } } } if (reportType == null) { throw new NotSupportedException("Missing definition for data type " + type.FullName); } if (reportType.UseToString) { string str = value.ToString(); if (string.IsNullOrEmpty(str)) { return(null); } return(new XElement(elementName, str)); } XElement resultElement = new XElement(elementName); if (maxDepth <= 0) { resultElement.Add(new XElement("ERROR: Maximum recursion reached")); } else { foreach (ReportBaseProperty reportProperty in reportType.Properties) { string[] accessors = reportProperty.Name.Split('.'); if (accessors.Length == 0) { throw new InvalidOperationException("Invalid property name \"" + (reportProperty.Name ?? "(null)") + "\""); } object currentValue = value; for (int i = 0; i < accessors.Length; ++i) { string accessor = accessors[i]; PropertyInfo propertyInfo = currentValue.GetType().GetProperty(accessor, BindingFlags.Instance | BindingFlags.Public); if (propertyInfo == null) { throw new InvalidOperationException(type.FullName + " does not define a property " + accessor); } currentValue = propertyInfo.GetValue(currentValue, new object[0]); if (currentValue == null) { continue; } } XObject propertyXml = GenerateReportProperty(reportProperty, currentValue, maxDepth); if (propertyXml != null) { resultElement.Add(propertyXml); } } } return(resultElement); }