将动态列表值转换为列表对象

时间:2016-03-22 02:34:03

标签: c# asp.net-mvc excel

我正在尝试导入Excel文件。这就是我的导入方法的样子。我在这里做的只是将excel数据添加到数据表中并将该数据表转换为动态列表并将其返回到控制器方法:

public List<dynamic> ImportFile(Stream stream)
{
    var productList = new List<Products>();
    using (var package = new ExcelPackage(stream))
    {
        var currentSheet = package.Workbook.Worksheets;
        var workSheet = currentSheet.First();

        //Creating a DataTable
        DataTable tbl = new DataTable();
        bool hasHeader = true; // adjust it accordingly( i've mentioned that this is a simple approach)

        //Creating the header
        foreach (var firstRowCell in workSheet.Cells[1, 1, 1, workSheet.Dimension.End.Column])
        {
            tbl.Columns.Add(hasHeader ? firstRowCell.Text : string.Format("Column {0}", firstRowCell.Start.Column));
        }

        var startRow = hasHeader ? 2 : 1;
        ////Inserting the stream into DataTable
        for (var rowNum = startRow; rowNum <= workSheet.Dimension.End.Row; rowNum++)
        {
            var wsRow = workSheet.Cells[rowNum, 1, rowNum, workSheet.Dimension.End.Column];
            var row = tbl.NewRow();
            foreach (var cell in wsRow)
            {
                row[cell.Start.Column - 1] = cell.Text;
            }
            tbl.Rows.Add(row);
        }
        //Convert datatable into dynamic list
        var dynamicDt = new List<dynamic>();
        foreach (DataRow row in tbl.Rows)
        {
            dynamic dyn = new ExpandoObject();
            dynamicDt.Add(dyn);
            foreach (DataColumn column in tbl.Columns)
            {
                var dic = (IDictionary<string, object>)dyn;
                dic[column.ColumnName] = row[column];
            }
        }
        return dynamicDt;
    }
}

这是我的控制器方法的样子:

[HttpPost]
public ActionResult Upload(HttpPostedFileBase upload)
{
    IExcelImporter reader = new ExcelImporter();
    var res = new List<dynamic>();
    List<Products> send = new List<Products>();
    if (ModelState.IsValid)
    {
        if (upload != null && upload.ContentLength > 0)
        {
            Stream stream = upload.InputStream;

            if (upload.FileName.EndsWith(".xlsx"))
            {
                //getting the dynamic list(returning dynamic list)
                res = reader.ImportFile(stream);

                //need to bind it a model-class(Products)
                send = res.Select(x=> 
                new Products
                {
                    ID = res.GetType().GetProperty("ID").ToString(),
                    Name = res.GetType().GetProperty("Name").ToString(),
                    //res.Select(e=>e.Price).ToString()//res.GetType().GetProperty("Price").GetValue(res, null).ToString()
                }).ToList(); 
            }
        }
    }
    return View("Index", send);
}

问题:我想要的是将动态列表绑定到模型类(Products)。这样我就可以将它返回到View。 如何将动态列表映射到列表产品?

这就是我的 IExcelImporter 的样子:

public interface IExcelImporter
{
    List<dynamic> ImportFile(Stream stream);
}

这就是我的产品模型的样子:

public class Products
{
    public string ID { get; set; }
    public string Name { get; set; }
    public string Price { get; set; }

}

有人可以告诉我如何解决这个问题。先感谢您。

1 个答案:

答案 0 :(得分:1)

总的来说,我认为没有理由使用dynamic作为返回类型。您的ImportFile方法可能会返回IEnumerable<Dictionary<string, string>>。另外,为什么DataTable?我猜您正在使用来自另一个使用DataTable数据库使用的示例进行大量复制粘贴,更好地创建一个额外的列表来存储列名并将它们用作字典中的键,这样可以节省你很多铸造。除非您显示的是高度简化的示例,否则您的ImportFile方法在可读性和性能方面都会产生大量开销。

直接回答你的问题,

您将获得PropertyInfo不存在的财产&#34; ID&#34; List<dynamic> - 不是你想要的。

res.GetType().GetProperty("ID").ToString() 

相反,你应该使用

// Get value of dynamic property "ID" of an item when iterating over of List<dynamic>
x.ID.ToString()