C#: Export a List of Objects to CSV with LINQ, Attributes, and Generics

Have you ever needed to transform data from in-memory C# objects to a CSV flat-file of a specific format?  Here’s an easy way to get the job done with C#, LINQ, and Generics.

First you need the Attribute you will use to mark up the properties on your exportable class:

/// <summary>
/// The name of the column for the CSV
/// generated by a list of objects with
/// properties marked with this attribute,
/// if Export is true.  Uses Order to order
/// the properties on export
/// </summary>
public class CsvColumnNameAttribute : Attribute
	public bool Export { get; set; }
	public int Order { get; set; }
	public string Name { get; set; }
	public CsvColumnNameAttribute()
		Export = true;
		Order = int.MaxValue; // so unordered columns are at the end

And here is how you use the attributes to mark up your class so you can export a list of instantiated objects:

public class MyClassToExport
	[CsvColumn(Name = "Activation Date", Order = 1)]	
	public DateTime Date { get; set; }
	[CsvColumn(Name = "Full Name", Order = 2)]
	public string User { get; set; }
	[CsvColumn(Name = "Account Type", Order = 3)]
	public int Level { get; set; }
	[CsvColumn(Name = "Account Action", Order = 4)]
	public string Action { get; set; }
	[CsvColumn(Export = false)]
	public DateTime Added { get; set; }

Then you need to code to actually create the CSV using LINQ and Generics:

/// <summary>
/// Generate a CSV as a string from a list
/// of objects that have the CsvColumnNameAttribute
/// applied
/// </summary>
public string GetCsv<T>(List<T> csvDataObjects)
	PropertyInfo[] propertyInfos = typeof(T).GetProperties();
	var sb = new StringBuilder();
	csvDataObjects.ForEach(d => sb.AppendLine(GetCsvDataRowSorted(d, propertyInfos)));
	return sb.ToString();
private string GetCsvDataRowSorted<T>(T csvDataObject, PropertyInfo[] propertyInfos)
	IEnumerable<string> valuesSorted = propertyInfos
		.Select(x => new
			Value = x.GetValue(csvDataObject, null),
			Attribute = (CsvColumnNameAttribute)Attribute.GetCustomAttribute(x, typeof(CsvColumnNameAttribute), false)
		.Where(x => x.Attribute != null && x.Attribute.Export)
		.OrderBy(x => x.Attribute.Order)
		.Select(x => GetPropertyValueAsString(x.Value));
	return String.Join(",", valuesSorted);
private string GetCsvHeaderSorted(PropertyInfo[] propertyInfos)
	IEnumerable<string> headersSorted = propertyInfos
		.Select(x => (CsvColumnNameAttribute)Attribute.GetCustomAttribute(x, typeof(CsvColumnNameAttribute), false))
		.Where(x => x != null && x.Export)
		.OrderBy(x => x.Order)
		.Select(x => x.Name);
	return String.Join(",", headersSorted);
private string GetPropertyValueAsString(object propertyValue)
	string propertyValueString;
	if (propertyValue == null)
		propertyValueString = "";
	else if (propertyValue is DateTime)
		propertyValueString = ((DateTime)propertyValue).ToString("dd MMM yyyy");
	else if (propertyValue is int)
		propertyValueString = propertyValue.ToString();
	else if (propertyValue is float)
		propertyValueString = ((float)propertyValue).ToString("#.####"); // format as you need it
	else if (propertyValue is double)
		propertyValueString = ((double)propertyValue).ToString("#.####"); // format as you need it
	else // treat as a string
		propertyValueString = @"""" + propertyValue.ToString().Replace(@"""", @"""""") + @""""; // quotes with 2 quotes
	return propertyValueString;

Once you have that code up in going in your application, you can export your list of objects to a CSV with just a couple lines of code:

// example usage
var export = new List<MyClassToExport>();
// TODO add items to list :)
var csv = GetCsv(export);

Hope this helps! And let me know if you have any suggestions or improvements.

This entry was posted in Attributes, C#, Generics, LINQ. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *