2012-02-16 38 views
5

目标:通用导出为CSV与表

我们的应用程序是使用多种类型的建(例如人,PersonSite(ICollection的),站点 - 我选择了这些类,因为他们有关系)。我们想要做的是能够从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类(类的子集):

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

所以CSVTable使用一个通用的类型,它是IObject提取(如在不同的类中使用)。

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

当添加一个子表,以一个表中,我们应当提供连接表达式将抓住正确类型的从主项中的项(人=> 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; 
    } 
} 

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

+1

伟大你有它的工作,你可以关闭它吗? – 2012-02-19 21:22:56

+4

我同意@MicahArmantrout;对于搜索类似问题的其他人,您是否可以将更新发布为答案并接受它?它也将防止将回答者试图解决您的问题..谢谢:-) – Jonno 2012-03-13 14:07:10

+2

@Whoami请张贴您的解决方案作为答案。你可以接受这个答案(有时你需要等待一两天才能完成)。如果你这样做,你会问问题和答案,因为你已经做了一些出色的工作。现在完成步骤(: – 2012-03-22 20:24:20

回答

0

抱歉耽搁,

所以最后,我们得到了它的工作是这样的:

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

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

希望这可以对其他人有用。