簡體   English   中英

使用表格通用導出到CSV

[英]Generic export to CSV with tables

目標:

我們的應用程序是使用多種類型構建的(例如Person,PersonSite(ICollection),Site - 我選擇了那些類,因為它們有關系)。 我們想要做的是能夠從excel表中的第一個類型(Person)導出一些屬性,然后從同一個excel文件中的第二個類型(PersonSite)導出一些其他屬性,但是在同一個新表中導出片。

結果應如下所示:

_________________   ________________________   ________________
|                 | |                        | |                |
|PERSON PROPERTIES| | PERSONSITE PROPERTIES  | |SITE PROPERTIES |
|_________________| |________________________| |________________|
|  Name Person 1  | |Relation type for item 1| | Name for item 1|
|_________________| |________________________| |________________|
                    |Relation type for item 2| | Name for item 2|
                    |________________________| |________________|
                    |Relation type for item 3| | Name for item 3|
                    |________________________| |________________|
 _________________   ________________________   ________________
|  Name Person 2  | |Relation type for item 1| | Name for item 1|
|_________________| |________________________| |________________|
                    |Relation type for item 2| | Name for item 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;}
}

Site類(子集):

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

所以我們決定編寫一個CSVExporter類,它使用表達式來檢索必須導出的屬性。

這是我們必須實現的方案:

____
                           |    |0..*
 ______________          __|____|______       1..* _______________
| CSV EXPORTER |________| CSV TABLE (T)|__________| CSV COLUMN (T)|
|______________|        |______________|          |_______________|
                               |
                               |1..*
                         ______|________
                        | CSV ROWS (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;
    }
}

有沒有人做過這樣的事情? 或者我們正走向錯誤的道路? 如果這似乎是一個好路徑,我們如何創建鏈接(關系)表達式並使用它來檢索在最后一次調用時使用的正確項目?

抱歉耽擱了,

最后,我們得到了這樣的工作:

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

這將應用任何子表的模板。

希望這對其他人有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM