I'm using MVC for REST so that I can take advantage of Razor for outputting different types. CSV is one of those outputs. Instead of writing this template for each input type:
ID,Created,Content
@foreach (var item in Model.TimeData)
{
<text>@item.ID,@item.Created,"@Html.Raw(item.Content.Replace("\"", "\"\""))"</text>
}
I wanted to make use of params and System.Linq.Expressions.Expression to write something like this:
@{
Html.WriteCsv<TimeObject>(Model.TimeData, p => p.ID, p => p.Created, p => p.Content);
}
I started writing a generic HtmlHelper and quickly realized I had problems with value types (memberExpression will be null). The code below attempts to just write out the CSV heading (ID,Created,Content), but it only outputs "Content" (because ID and Created are value types (int and DateTime).
public static void WriteCsv<TModel>(this HtmlHelper htmlHelper, List<TModel> list, params Expression<Func<TModel, object>>[] expressions)
{
foreach (var expression in expressions)
{
MemberExpression memberExpression = expression.Body as MemberExpression;
if (memberExpression != null)
{
var propertyInfo = (PropertyInfo)memberExpression.Member;
htmlHelper.ViewContext.Writer.Write(propertyInfo.Name + Environment.NewLine);
}
}
}
I tried replacing object with dynamic, thinking that would work, but when I quick watch expression.Body, it still seems to think it's dealing with an object (the DebugView property is (System.Object)$p.ID).
Is this impossible in C# 4.0?
Here's the type I'm using it on:
[DataContract(IsReference = true, Namespace = "urn:test:TimeObject")]
public class TimeObject
{
[DataMember]
public long ID { get; set; }
[DataMember]
public string Content { get; set; }
[DataMember]
public DateTime Created { get; set; }
}
(FieldInfo)