Цель:
Наше приложение построено с использованием нескольких типов (например, Person, PersonSite (ICollection), Site - я выбрал эти классы, потому что они связаны).Мы хотим экспортировать некоторые свойства из первого типа (Person) в таблицу Excel, а затем экспортировать некоторые другие свойства из второго типа (PersonSite) в тот же файл Excel, но в новую таблицу в той же таблице.лист.
Результат должен выглядеть следующим образом:
_________________ ________________________ ________________
| | | | | |
|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;}
}
Класс сайта (подмножество):
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 tи таблица 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;
}
}
Кто-нибудь когда-нибудь делал что-то подобное?Или мы идем по неверному пути?Если это хороший путь, как мы можем создать выражение связи (отношения) и использовать его для получения правильных элементов, которые будут использоваться при последнем вызове?