/// <summary> /// Loads items from the specified <see cref="StreamReader"/>. /// </summary> /// <typeparam name="T"> /// The type of the output items. /// </typeparam> /// <param name="r"> /// The input <see cref="StreamReader"/>. /// </param> /// <param name="cultureInfo"> /// The input culture. /// </param> /// <returns> /// A list of items. /// </returns> /// <exception cref="System.FormatException"> /// Unit not recognized /// </exception> public static IList <T> Load <T>(StreamReader r, CultureInfo cultureInfo = null) { if (cultureInfo == null) { cultureInfo = CultureInfo.InvariantCulture; } var separator = cultureInfo.TextInfo.ListSeparator; var type = typeof(T); // Get the properties from the type var properties = type.GetTypeInfo().DeclaredProperties.ToArray(); var header = r.ReadLine(); if (header == null) { return(null); } // Parse the header var headers = CsvFile.SplitLine(header, separator[0]); int n = headers.Length; var propertyDescriptors = new PropertyInfo[n]; var units = new IQuantity[n]; for (int i = 0; i < n; i++) { string name, unit; CsvFile.SplitHeader(headers[i], out name, out unit); propertyDescriptors[i] = properties.First(pi => pi.Name == name); var quantityType = CsvFile.GetQuantityType(propertyDescriptors[i].PropertyType); // Set the unit if it is a IQuantity based property if (quantityType != null) { IQuantity displayUnit; if (UnitProvider.Default.TryGetUnit(quantityType, unit, out displayUnit)) { units[i] = displayUnit; } else { throw new FormatException("Unit " + unit + " not recognized"); } } } // Read the rows var items = new List <T>(); int lineNumber = 1; while (!r.EndOfStream) { lineNumber++; var line = r.ReadLine(); if (line == null) { continue; } var values = CsvFile.SplitLine(line, separator[0]); if (values.Length != n) { throw new FormatException("Wrong number of columns on line " + lineNumber); } var item = Activator.CreateInstance <T>(); for (int i = 0; i < headers.Length; i++) { var value = ChangeType(values[i], propertyDescriptors[i].PropertyType, units[i], cultureInfo); propertyDescriptors[i].SetValue(item, value, null); } items.Add(item); } return(items); }
/// <summary> /// Saves the items to the specified <see cref="StreamWriter"/>. /// </summary> /// <typeparam name="T"> /// The type of the items /// </typeparam> /// <param name="items"> /// The items. /// </param> /// <param name="streamWriter"> /// The <see cref="StreamWriter"/>. /// </param> /// <param name="cultureInfo"> /// The output culture. /// </param> public static void Save <T>(IEnumerable <T> items, StreamWriter streamWriter, CultureInfo cultureInfo = null) { if (cultureInfo == null) { cultureInfo = CultureInfo.InvariantCulture; } var separator = cultureInfo.TextInfo.ListSeparator; var type = typeof(T); var properties = type.GetTypeInfo().DeclaredProperties .Where(CsvIgnoreAttribute.IsNotIgnored) .OrderBy(CsvColumnAttribute.GetColumn) .ToList(); int n = properties.Count; var displayUnits = new IQuantity[n]; for (int i = 0; i < n; i++) { if (i > 0) { streamWriter.Write(separator); } streamWriter.Write(properties[i].Name); var quantityType = CsvFile.GetQuantityType(properties[i].PropertyType); if (quantityType != null) { string unitSymbol; displayUnits[i] = UnitProvider.Default.GetDisplayUnit(quantityType, out unitSymbol); streamWriter.Write(" [{0}]", unitSymbol); } } streamWriter.WriteLine(); int j = 0; foreach (var item in items) { if (j++ > 0) { streamWriter.WriteLine(); } for (int i = 0; i < n; i++) { if (i > 0) { streamWriter.Write(separator); } var value = properties[i].GetValue(item, null); var q = value as IQuantity; if (q != null && displayUnits[i] != null) { streamWriter.Write(string.Format(cultureInfo, "{0}", q.ConvertTo(displayUnits[i]))); } else { streamWriter.Write(string.Format(cultureInfo, "{0}", value)); } } } }