【问题标题】:Generic export to CSV with tables带表格的通用导出到 CSV
【发布时间】:2012-03-07 15:28:31
【问题描述】:

目标:

我们的应用程序是使用多种类型构建的(例如 Person、PersonSite(ICollection)、Site - 我选择这些类是因为它们之间存在关系)。我们想要做的是能够从 excel 表中的第一种类型(Person)导出一些属性,然后在同一个 excel 文件但在同一个新表中从第二种类型(PersonSite)导出一些其他属性表。

结果应该是这样的:

_________________ ________________________ ________________ | | | | | | |人员属性| |个人网站属性 | |网站属性 | |_________________| |________________________| |________________| |姓名 人 1 | |第 1 项的关系类型| |第 1 项的名称| |_________________| |________________________| |________________| |第 2 项的关系类型| |第 2 项的名称| |________________________| |________________| |第 3 项的关系类型| |第 3 项的名称| |________________________| |________________| _________________ ________________________ ________________ |姓名 人 2 | |第 1 项的关系类型| |第 1 项的名称| |_________________| |________________________| |________________| |第 2 项的关系类型| |第 1 项的名称| |________________________| |________________|

因此,对于列表中包含的每个 PersonSite,我们希望创建一个将插入到 Person 表之后的表。

这就是 Person 类(类的子集)的外观:

public class Person : IObject
{
   public ICollection<PersonSite> PersonSites {get;set;}
}

现在是 PersonSite 类(子集):

public class PersonSite : IObject
{
   public Person Person {get;set;}
   public Site Site {get;set;}
   public RelationType RelationType {get;set;}
}

站点类(子集):

public class Site : IObject
{
   public ICollection<PersonSite> PersonSites {get;set;}
}

所以我们决定编写一个 CSVExporter 类,它使用表达式来检索必须导出的属性。

这是我们必须实施的方案:

____ | |0..* ______________ __|____|______ 1..* _______________ | CSV 导出器 |________| CSV 表 (T)|__________| CSV 列 (T)| |______________| |______________| |_______________| | |1..* ______|________ | CSV 行 (T) | |_______________|

因此 CSVTable 使用 IObject 泛型类型(在不同的类中使用)。

一个表可以有多个表(例如,Person 表有一个 PersonSite 表,一个 PersonSite 表有一个 Site 表)。但是使用的类型是不同的,因为我们在不同的类中导航(这些类必须有关系)。

当向表中添加子表时,我们应该提供 en 表达式,该表达式将从主要项目中获取正确类型的项目 (Person => Person.PersonSite)

所以我们为表格编写了以下代码:

public class CSVExportTable<T>
    where T : IObject
{

    private Matrix<string> Matrix { get; set; }
    private ICollection<CSVExportTableColumn<T>> Columns { get; set; }
    private ICollection<CSVExportTableRow<T>> Rows { get; set; }
    private ICollection<CSVExportTable<IObject>> SubTables { get; set; }
    private Expression<Func<T, object>> Link { get; set; }


    public CSVExportTable()
    {
        this.Matrix = new Matrix<string>();
        this.Columns = new List<CSVExportTableColumn<T>>();
        this.SubTables = new List<CSVExportTable<IObject>>();
        this.Rows = new List<CSVExportTableRow<T>>();
    }

    public CSVExportTable<R> AddSubTable<R>(Expression<Func<T, object>> link) where R : IObject
    {
        /* This is where we create the link between the main table items and the subtable items (= where we retreive Person => Person.PersonSites as an ICollection<R> since the subtable has a different type (T != R but they have the same interface(IObject))*/
    }

    public void AddColumn(Expression<Func<T, object>> exportProperty)
    {
        this.Columns.Add(new CSVExportTableColumn<T>(exportProperty));
    }

    public Matrix<string> GenerateMatrix()
    {
        int rowIndex= 0;
        foreach (CSVExportTableRow<T> row in this.Rows)
        {
            int columnIndex = 0;
            foreach (CSVExportTableColumn<T> column in this.Columns)
            {
                this.Matrix = this.Matrix.AddValue(rowIndex, columnIndex, ((string)column.ExportProperty.Compile().DynamicInvoke(row.Item)));
                columnIndex++;
            }
            rowIndex++;
        }
        return this.Matrix;
    }

    public Matrix<string> ApplyTemplate(ICollection<T> items)
    {
        // Generate rows
        foreach (T item in items)
        {
            this.Rows.Add(new CSVExportTableRow<T>(item));
        }
        // Instantiate the matrix
        Matrix<string> matrix = new Matrix<string>();

        // Generate matrix for every row
        foreach (var row in this.Rows)
        {
            matrix = GenerateMatrix();
            // Generate matrix for every sub table
            foreach (var subTable in this.SubTables)
            {
                // This it where we should call ApplyTemplate for the current subTable with the elements that the link expression gave us(ICollection).
            }
        }
        return matrix;
    }
}

最后是 CSVExportTableColumn 类:

public class CSVExportTableColumn<T> where T : IObject
{
    public Expression<Func<T, object>> ExportProperty { get; set; }

    public CSVExportTableColumn(Expression<Func<T, object>> exportProperty)
    {
        this.ExportProperty = exportProperty;
    }
}

有没有人做过类似的事情?还是我们走错了路? 如果这似乎是一条不错的路径,我们如何创建链接(关系)表达式并使用它来检索正确的项目以在最后一次调用中使用?

【问题讨论】:

  • 太好了,你可以关闭它吗?
  • 我同意@MicahArmantrout;对于其他搜索类似问题的人,您能否发布您的更新作为答案并接受它?它还将阻止回答者尝试解决您的问题..谢谢:-)
  • @Whoami 请发布您的解决方案作为答案。您可以接受该答案(有时您需要等待一两天才能做到这一点)。如果您这样做,将会对您的问题和答案进行投票,因为您已经做了一些出色的工作。现在完成步骤(:
  • @JeroenWiertPluimers 说了什么。这是处理这种情况的正确方法。谢谢。

标签: c# generics expression export-to-csv


【解决方案1】:

抱歉耽搁了,

所以最后,我们让它像这样工作:

public Matrix<string> ApplyTemplate(object items)
    {
        ICollection<T> castedItems = new List<T>();
        // Cast items as a List<T>
        if (items is List<T>)
        {
            castedItems = (ICollection<T>)items;
        }
        else if (items is HashSet<T>)
        {
            castedItems = ((HashSet<T>)items).ToList();
        }
        // Generate rows
        foreach (T item in castedItems)
        {
            this.Rows.Add(new CSVExportTableRow<T>(item));
        }
        // Instantiate the matrix
        Matrix<string> matrix = new Matrix<string>();

        // Generate matrix for every row
        foreach (var row in this.Rows)
        {
            matrix = GenerateMatrix();
            // Generate matrix for every sub table
            foreach (var subTable in this.SubTables)
            {
                matrix = matrix.AddMatrix(subTable.ApplyTemplate(this.Link.Compile().DynamicInvoke(row.Item)));
            }
        }
        return matrix;
    }

这将为任何子表应用模板。

希望这对其他人有用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-17
    • 2018-07-09
    • 2016-09-10
    • 2014-03-22
    • 2020-12-05
    相关资源
    最近更新 更多