Who*_*ami 5 c# generics expression export-to-csv
目标:
我们的应用程序是使用多种类型构建的(例如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;}
}
Run Code Online (Sandbox Code Playgroud)
现在是PersonSite类(子集):
public class PersonSite : IObject
{
public Person Person {get;set;}
public Site Site {get;set;}
public RelationType RelationType {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
Site类(子集):
public class Site : IObject
{
public ICollection<PersonSite> PersonSites {get;set;}
}
Run Code Online (Sandbox Code Playgroud)
所以我们决定编写一个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;
}
}
Run Code Online (Sandbox Code Playgroud)
最后这里是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;
}
}
Run Code Online (Sandbox Code Playgroud)
有没有人做过这样的事情?或者我们正走向错误的道路?如果这似乎是一个好路径,我们如何创建链接(关系)表达式并使用它来检索在最后一次调用时使用的正确项目?
抱歉耽搁了,
最后,我们让它像这样工作:
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;
}
Run Code Online (Sandbox Code Playgroud)
这会将模板应用于任何子表。
希望这对其他人有用。
| 归档时间: |
|
| 查看次数: |
836 次 |
| 最近记录: |