2011-04-18 128 views
3

我正在使用MVC for REST,以便我可以利用Razor来输出不同类型的数据。 CSV是其中的一个输出。而不是写这个模板为每个输入类型:对值类型和引用类型使用C#LINQ表达式

ID,Created,Content 
@foreach (var item in Model.TimeData) 
{ 
<text>@item.ID,@item.Created,"@Html.Raw(item.Content.Replace("\"", "\"\""))"</text> 
} 

我想利用paramsSystem.Linq.Expressions.Expression写的是这样的:

@{ 
    Html.WriteCsv<TimeObject>(Model.TimeData, p => p.ID, p => p.Created, p => p.Content); 
} 

我开始写一个通用的HtmlHelper,并很快意识到我有值类型的问题(memberExpression将为null)。下面的代码试图只写出来的CSV标题(ID,创建,内容),但它仅输出“内容”(因为ID和创建的值类型(intDateTime)。

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); 
     } 
    } 
} 

我试图更换objectdynamic,认为会的工作,但是当我快看expression.Body,似乎仍然认为它在处理一个对象(DebugView属性为(System.Object)$p.ID)。

这是不可能在C#4.0?

下面是我使用它的类型:

[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; } 
} 
+2

这是切你的问题,但使用自定义的ActionResult会更好。你甚至可以在这里使用:http://notesfor.net/post/2010/06/28/AspNet-custom-ActionResult-CSV.aspx – Talljoe 2011-04-18 19:05:13

+0

咦?你的代码应该工作。 – SLaks 2011-04-18 19:05:41

+0

你确定值类型是属性吗?也许他们是需要你将字段转换为'(FieldInfo)' – Jose 2011-04-18 19:10:46

回答

6

在表达式引用值类型的情况下,编译器必须装入引用;它隐含地这样做。这种复杂性意味着值类型成员表达式的表达式树不仅仅是一个MemberExpression,所以你的转换返回null。

下面是从一个值类型或引用类型成员的表达,从this question所获得的属性名称的通用解决方案:

private string GetPropertyName(Expression<Func<object, object>> f) { 
    var body = f.Body; 
    if (body.NodeType==ExpressionType.Convert) 
     body = ((UnaryExpression) body).Operand; 
    if ((body as MemberExpression) != null) { 
     return (body as MemberExpression).Member.Name; 
    } 
    return ""; 
}