2012-02-16 35 views
5

Mục tiêu:Generic xuất khẩu sang CSV với các bảng

ứng dụng của chúng tôi được xây dựng sử dụng nhiều loại (ví dụ Person, PersonSite (ICollection), trang web - Tôi chọn những lớp học bởi vì họ có một mối quan hệ). Những gì chúng tôi muốn làm là có thể xuất một số thuộc tính từ kiểu đầu tiên (Person) trong bảng excel và sau đó xuất một số thuộc tính khác từ kiểu thứ hai (PersonSite) bên trong cùng một tệp excel nhưng trong một bảng mới trên cùng một tấm.

Kết quả sẽ giống như thế này:

 
_________________ ________________________ ________________ 
|     | |      | |    | 
|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| 
        |________________________| |________________| 

Vì vậy, đối với mỗi PersonSite chứa trong danh sách, chúng tôi muốn tạo ra một bảng mà sẽ được chèn ngay sau bàn của Người.

Vì vậy, đây là cách tìm lớp Person (tập hợp con của lớp):

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

Bây giờ lớp PersonSite (nhóm nhỏ):

public class PersonSite : IObject 
{ 
    public Person Person {get;set;} 
    public Site Site {get;set;} 
    public RelationType RelationType {get;set;} 
} 

Lớp Site (nhóm nhỏ):

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

Vì vậy, chúng tôi quyết định viết một lớp CSVExporter sử dụng các biểu thức để truy xuất các thuộc tính phải đã xuất.

Đây là chương trình chúng ta phải thực hiện điều này:

      
          ____ 
          | |0..* 
______________   __|____|______  1..* _______________ 
| CSV EXPORTER |________| CSV TABLE (T)|__________| CSV COLUMN (T)| 
|______________|  |______________|   |_______________| 
           | 
           |1..* 
         ______|________ 
         | CSV ROWS (T) | 
         |_______________| 

Vì vậy, các CSVTable sử dụng một loại chung chung mà là IObject (như được sử dụng trong các lớp khác nhau).

Bảng có thể có nhiều bảng (ví dụ: bảng Person có bảng PersonSite và bảng PersonSite có bảng Site). Nhưng loại được sử dụng là khác nhau vì chúng ta điều hướng qua các lớp khác nhau (các lớp đó phải có mối quan hệ).

Khi thêm một subtable vào một bảng chúng ta nên cung cấp en biểu rằng sẽ lấy các hạng mục đúng loại từ các hạng mục chính (Person => Person.PersonSite)

Vì vậy, chúng tôi đã viết những đoạn mã sau đây cho bảng:

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

Và cuối cùng ở đây là lớp 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; 
    } 
} 

có ai đã từng làm điều gì đó như thế? Hay chúng ta đang đi đến con đường sai lầm? Nếu điều này có vẻ là một con đường tốt, làm thế nào chúng ta có thể tạo biểu thức liên kết (mối quan hệ) và sử dụng nó để lấy các mục chính xác để sử dụng trong cuộc gọi cuối cùng?

+1

Thật tuyệt khi bạn làm việc đó bạn có thể đóng nó không? –

+4

Tôi đồng ý với @MicahArmantrout; Đối với những người khác đang tìm kiếm các sự cố tương tự, bạn có thể đăng cập nhật của mình làm câu trả lời và chấp nhận không? Nó cũng sẽ ngăn chặn sẽ là người trả lời từ cố gắng để giải quyết câu hỏi của bạn .. cảm ơn :-) – Jonno

+2

@Whoami xin vui lòng gửi giải pháp của bạn như là một câu trả lời. Bạn có thể chấp nhận câu trả lời đó (đôi khi bạn cần chờ một hoặc hai ngày để làm điều đó). Sẽ upvote cả câu hỏi và câu trả lời của bạn nếu bạn làm, như bạn đã làm một số công việc tuyệt vời rồi. Bây giờ là bước hoàn thiện (: –

Trả lời

0

Xin lỗi vì sự chậm trễ,

Vì vậy, cuối cùng, chúng tôi đã nhận nó làm việc như thế này:

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

này sẽ áp dụng mẫu cho bất kỳ bảng phụ.

Hy vọng điều này có thể hữu ích cho người khác.

Các vấn đề liên quan