What follows is a generic class for generating CSV files.
Usage
CsvWriter<MyObject> writer = new CsvWriter<MyObject>(); writer.Header = true; writer.AddColumn("Id", x => x.Id.ToString()); writer.AddColumn("Name", x => x.Name); writer.AddColumn("Price", x => x.Price.ToString()); writer.AddColumn("Guid", x => x.Guid); writer.AddColumn("Description", x => x.Description); writer.AddColumn("Url", x => x.Url); IEnumerable<MyObject> objects = Load(); string csv = writer.WriteToString(objects); File.WriteAllText("objects.csv", csv);
Classes
class CsvWriter<T> { private readonly List<CsvColumn<T>> _columns = new List<CsvColumn<T>>(); public bool Header { get; set; } public bool QuoteAll { get; set; } public IEnumerable<CsvColumn<T>> Columns { get { return _columns; } } public void AddColumn(string name, Func<T, string> value) { if (name == null) throw new ArgumentNullException("name"); if (value == null) throw new ArgumentNullException("value"); foreach (CsvColumn<T> column in _columns) if (column.Name == name) throw new Exception("Column with same name already added."); _columns.Add(new CsvColumn<T>(name, value)); } public string WriteToString(IEnumerable<T> items) { if (items == null) throw new ArgumentNullException("items"); StringWriter writer = new StringWriter(); WriteToStream(writer, items); return writer.ToString(); } public void WriteToStream(TextWriter stream, IEnumerable<T> items) { if (stream == null) throw new ArgumentNullException("stream"); if (items == null) throw new ArgumentNullException("items"); if (Header) WriteHeader(stream); foreach (T item in items) WriteRow(stream, item); } private void WriteHeader(TextWriter stream) { bool first = true; foreach (CsvColumn<T> column in _columns) { if (first) first = false; else stream.Write(','); WriteValue(stream, column.Name); } stream.Write('\n'); } private void WriteRow(TextWriter stream, T item) { if (item == null) return; bool first = true; foreach (CsvColumn<T> column in _columns) { if (first) first = false; else stream.Write(','); WriteValue(stream, column.Value(item)); } stream.Write('\n'); } private void WriteValue(TextWriter stream, string value) { if (value == null) return; if (QuoteAll || ContainsAny(value, '\"', ',', '\x0A', '\x0D')) { stream.Write("\""); stream.Write(value.Replace("\"", "\"\"")); stream.Write("\""); } else { stream.Write(value); } } private static bool ContainsAny(string value, params char[] characters) { return value.IndexOfAny(characters) != -1; } } class CsvColumn<T> { public string Name { get; private set; } public Func<T, string> Value { get; private set; } public CsvColumn(string name, Func<T, string> value) { if (name == null) throw new ArgumentNullException("name"); if (value == null) throw new ArgumentNullException("value"); Name = name; Value = value; } }