I have refactored out a generic CSV builder for List using lambda expressions to access the correct values
public static string ToCsv<TModel>(this List<TModel> list, string delimiter, string lineBreak, string valueWrap, params Expression<Func<TModel, object>>[] expressions)
{
var sb = new StringBuilder();
var headers = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, GetPropertyName(m))).ToArray();
sb.Append(String.Format("{0}{1}", String.Join(delimiter, headers), lineBreak));
foreach (var listItem in list)
{
var values = expressions.Select(m => String.Format("{0}{1}{0}", valueWrap, m.Compile()(listItem))).ToArray();
sb.Append(String.Format("{0}{1}", String.Join(delimiter, values), lineBreak));
}
return sb.ToString();
}
This works well, however because I am trying to move this into some common code for several projects across several servers to access. I cannot reference the System.Web.Mvc assembly
Is there a good way to access the DisplayName Attribute and if that doesnot exist, access the variable name?
My current attempt access the ((MemberExpression) expression.Body).Member.Name however it will not work if it has to convert a value to string. (ie passing an int and implicitly converting)
A second attempt of iterating over the attributes did not work for inner class (ie model => model.innerClass.property)
With a couple simple helper functions, you can eliminate all reference to the System.Web.Mvc assembly. You’ll also notice in the example below that (model => model.member.property) works.