目标 :
我们的应用程序是使用多种类型构建的(例如,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;
}
}
有没有人做过这样的事情?还是我们走错了路?如果这似乎是一条不错的路径,我们如何创建链接(关系)表达式并使用它来检索要在最后一次调用中使用的正确项目?