/// <summary> /// 'Flatten' a value (if it is an array or structure) into something that can be /// stored in a flat database table. /// </summary> /// <param name="name">The column name.</param> /// <param name="units">The units of the value.</param> /// <param name="value">The value to store.</param> /// <param name="row">Row to store value into to.</param> private void FlattenValueIntoRow(string name, string units, object value, DataRow row) { if (value == null) { AddColumnToTable(row.Table, name); } else if (value.GetType() == typeof(DateTime) || value.GetType() == typeof(string) || !value.GetType().IsClass) { // Scalar var newColumnName = AddColumnToTable(row.Table, name, value.GetType()); row[newColumnName] = value; } else if (value.GetType().GetInterface("IList") != null) { // List IList array = value as IList; for (int arrayIndex = 0; arrayIndex < array.Count; arrayIndex++) { string heading = name; heading += "(" + (arrayIndex + 1).ToString() + ")"; object arrayElement = array[arrayIndex]; FlattenValueIntoRow(heading, units, arrayElement, row); // recursion } } } else { // A struct or class foreach (PropertyInfo property in ReflectionUtilities.GetPropertiesSorted(value.GetType(), BindingFlags.Instance | BindingFlags.Public)) { object[] attrs = property.GetCustomAttributes(true); string propUnits = null; bool ignore = false; foreach (object attr in attrs) { if (attr is XmlIgnoreAttribute) { ignore = true; continue; } Core.UnitsAttribute unitsAttr = attr as Core.UnitsAttribute; if (unitsAttr != null) { propUnits = unitsAttr.ToString(); } } if (ignore) { continue; } string heading = name + "." + property.Name; object classElement = property.GetValue(value, null); FlattenValueIntoRow(heading, propUnits, classElement, row); // recursion } } }
/// <summary> /// 'Flatten' a value (if it is an array or structure) into something that can be /// stored in a flat database table. /// </summary> /// <param name="name"></param> /// <param name="units"></param> /// <param name="value"></param> /// <param name="newColumnNames"></param> /// <param name="newColumnUnits"></param> /// <param name="newValues"></param> private static void FlattenValue(string name, string units, object value, List <string> newColumnNames, List <string> newColumnUnits, List <object> newValues) { if (value == null || value.GetType() == typeof(DateTime) || value.GetType() == typeof(string) || !value.GetType().IsClass) { // Scalar newColumnNames.Add(name); newColumnUnits.Add(units); newValues.Add(value); } else if (value.GetType().IsArray) { // Array Array array = value as Array; for (int columnIndex = 0; columnIndex < array.Length; columnIndex++) { string heading = name; heading += "(" + (columnIndex + 1).ToString() + ")"; object arrayElement = array.GetValue(columnIndex); FlattenValue(heading, units, arrayElement, newColumnNames, newColumnUnits, newValues); // recursion } } else if (value.GetType().GetInterface("IList") != null) { // List IList array = value as IList; for (int columnIndex = 0; columnIndex < array.Count; columnIndex++) { string heading = name; heading += "(" + (columnIndex + 1).ToString() + ")"; object arrayElement = array[columnIndex]; FlattenValue(heading, units, arrayElement, newColumnNames, newColumnUnits, newValues); // recursion } } } else { // A struct or class foreach (PropertyInfo property in ReflectionUtilities.GetPropertiesSorted(value.GetType(), BindingFlags.Instance | BindingFlags.Public)) { object[] attrs = property.GetCustomAttributes(true); string propUnits = null; bool ignore = false; foreach (object attr in attrs) { if (attr is XmlIgnoreAttribute) { ignore = true; continue; } Core.UnitsAttribute unitsAttr = attr as Core.UnitsAttribute; if (unitsAttr != null) { propUnits = unitsAttr.ToString(); } } if (ignore) { continue; } string heading = name + "." + property.Name; object classElement = property.GetValue(value, null); FlattenValue(heading, propUnits, classElement, newColumnNames, newColumnUnits, newValues); // recursion } } }
/// <summary> /// 'Flatten' a value (if it is an array or structure) into something that can be /// stored in a flat database table. /// </summary> /// <param name="name">The column name.</param> /// <param name="units">The units of the value.</param> /// <param name="value">The value to store.</param> /// <param name="row">Row to store value into to.</param> private void FlattenValueIntoRow(string name, string units, object value, DataRow row) { if (value == null) { AddColumnToTable(row.Table, name); } else if (value.GetType() == typeof(DateTime) || value.GetType() == typeof(string) || !value.GetType().IsClass) { // Scalar Type dataType = value.GetType(); if (dataType.IsEnum) { dataType = typeof(string); } var newColumnName = AddColumnToTable(row.Table, name, dataType); row[newColumnName] = value; } else if (value.GetType().GetInterface("IList") != null) { // List IList array = value as IList; // Determine if there is an array specification e.g. (2) at the end of the heading var regex = new Regex("(.+)\\(([0-9]+)\\)$"); var match = regex.Match(name); for (int i = 0; i < array.Count; i++) { if (match.Success) { // Found an array specification e.g. col(1) var heading = match.Groups[1].ToString(); var startIndex = Convert.ToInt32(match.Groups[2].ToString()) - 1; heading = string.Format("{0}({1})", heading, startIndex + i + 1); object arrayElement = array[i]; FlattenValueIntoRow(heading, units, arrayElement, row); } else { // Found no array specification - output whole array. var heading = string.Format("{0}({1})", name, i + 1); object arrayElement = array[i]; FlattenValueIntoRow(heading, units, arrayElement, row); // recursion } } } else { // A struct or class foreach (PropertyInfo property in ReflectionUtilities.GetPropertiesSorted(value.GetType(), BindingFlags.Instance | BindingFlags.Public)) { object[] attrs = property.GetCustomAttributes(true); string propUnits = null; bool ignore = false; foreach (object attr in attrs) { if (attr is JsonIgnoreAttribute) { ignore = true; continue; } Core.UnitsAttribute unitsAttr = attr as Core.UnitsAttribute; if (unitsAttr != null) { propUnits = unitsAttr.ToString(); } } if (ignore) { continue; } string heading = name + "." + property.Name; object classElement = property.GetValue(value, null); FlattenValueIntoRow(heading, propUnits, classElement, row); // recursion } } }
/// <summary> /// 'Flatten' the object passed in, into a list of columns ready to be added /// to a data table. /// </summary> /// <param name="name">Column name where the value came from.</param> /// <param name="units">Units of measurement; null if not applicable</param> /// <param name="value">The object to be analyzed and flattened</param> /// <param name="rowIndex">The row index of the specified value.</param> /// <param name="flattenedColumns">The returned flattened columns.</param> /// <returns>The list of values that can be written to a data table</returns> private static void FlattenValue(string name, string units, object value, int rowIndex, List <IReportColumn> flattenedColumns) { if (value == null || value.GetType() == typeof(DateTime) || value.GetType() == typeof(string) || !value.GetType().IsClass) { // Scalar IReportColumn flattenedColumn = flattenedColumns.Find(col => col.Name == name); if (flattenedColumn == null) { flattenedColumn = new ReportColumnWithValues(name, units); InsertColumn(flattenedColumn, flattenedColumns); } // Ensure all columns have the correct number of values. foreach (IReportColumn column in flattenedColumns) { if (column is ReportColumnConstantValue) { } else { while (column.Values.Count <= rowIndex) { column.Values.Add(null); } } } flattenedColumn.Values[rowIndex] = value; } else if (value.GetType().IsArray) { // Array Array array = value as Array; for (int columnIndex = 0; columnIndex < array.Length; columnIndex++) { string heading = name; heading += "(" + (columnIndex + 1).ToString() + ")"; object arrayElement = array.GetValue(columnIndex); FlattenValue(heading, units, arrayElement, rowIndex, flattenedColumns); // recursion } } else if (value.GetType().GetInterface("IList") != null) { // List IList array = value as IList; for (int columnIndex = 0; columnIndex < array.Count; columnIndex++) { string heading = name; heading += "(" + (columnIndex + 1).ToString() + ")"; object arrayElement = array[columnIndex]; FlattenValue(heading, units, arrayElement, rowIndex, flattenedColumns); // recursion } } else { // A struct or class foreach (PropertyInfo property in ReflectionUtilities.GetPropertiesSorted(value.GetType(), BindingFlags.Instance | BindingFlags.Public)) { object[] attrs = property.GetCustomAttributes(true); string propUnits = null; bool ignore = false; foreach (object attr in attrs) { if (attr is XmlIgnoreAttribute) { ignore = true; continue; } Core.UnitsAttribute unitsAttr = attr as Core.UnitsAttribute; if (unitsAttr != null) { propUnits = unitsAttr.ToString(); } } if (ignore) { continue; } string heading = name + "." + property.Name; object classElement = property.GetValue(value, null); FlattenValue(heading, propUnits, classElement, rowIndex, flattenedColumns); } } }