具有协方差的DataGridView?
DataGridView with covariance?
我有如下代码(我已经对其进行了泛化和简化以仅代表手头的问题)。该代码有效,即它接收 DataGridView.DataSource
并最终使用 EPPlus
将数据输出到 Excel 文件。我认为我的问题与协方差以及如何使用它有关。
因此您看到它根据在 DataSource
中找到的类型构建 newList
。然后再往下一点,它使用此类型独有的属性 someClassObject.Name, .Address and .Phone
添加数据。
我的问题是大约有 75 种不同的 class 可以通过 DataGridView
参数传入。每个 class 都有自己独特的属性(即不一定是名称、地址、Phone),尽管给定 DataGridView.DataSource
中的所有对象都是相同的 class。
我可以有一个基于 type.FullName
的 giant switch 语句,然后每个语句都有自己的 for 循环来将 属性 值分配给单元格.那会起作用,但会非常麻烦。有更好的方法吗?
public void openExcelReport(ref DataGridView dataGridView, bool bolSave = false, bool bolOpen = true, string pageTitle = "EXPORTED DATA")
{
// put dataGridView.DataSource into a List
object firstItem = null;
var myDataSource = dataGridView.DataSource;
var myList = ((System.Windows.Forms.BindingSource)dataGridView.DataSource).List;
firstItem = ((System.Collections.IList)myList)[0];
var type = firstItem.GetType();
Type PROJECT1_TYPE = typeof(Project1.SomeClass);
Type PROJECT2_TYPE = typeof(Project2.SomeOtherClass); // many more of these
dynamic newList = null;
if (type.FullName.Equals(PROJECT1_TYPE.FullName))
{
newList = new List<Project1.SomeClass>();
foreach (Project1.SomeClass someClassObject in myList)
{
newList.Add(someClassObject);
}
}
ExcelPackage package = new ExcelPackage();
using ((package)) // use EPPlus
{
// Create the worksheet
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1");
// Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
System.Data.DataTable dataTable = new System.Data.DataTable();
dataTable.Columns.Add("Id");
dataTable.Columns.Add("FirstColumn", typeof(string));
dataTable.Columns.Add("SecondColumn", typeof(string));
dataTable.Columns.Add("ThirdColumn", typeof(string));
dataTable.Columns[0].AutoIncrement = true;
var column_id = 0;
foreach (Project1.SomeClass someClassObject in "FirstColumn")
{
DataRow dataRow = dataTable.NewRow();
dataRow["FirstColumn"] = someClassObject.Name;
dataRow["SecondColumn"] = someClassObject.Address;
dataRow["ThirdColumn"] = someClassObject.Phone
dataTable.Rows.Add(dataRow);
column_id += 1;
}
// worksheet is now populated, so save Excel File
...
}
您可以将它移到 class 实现中,而不是在此函数中执行 DataRow
创建,使用通用接口来强制执行它,例如:
public interface DataRowConvertable
{
DataRow GetDataRow();
}
public class SomeClass : DataRowConvertable
{
public SomeClass() { }
public SomeClass(string name, string address, string phone)
{
Name = name;
Address = address;
Phone = phone;
}
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public DataRow GetDataRow()
{
DataRow row = GetDataTable().NewRow();
row["Name"] = this.Name;
row["Address"] = this.Address;
row["Phone"] = this.Phone;
return row;
}
public static DataTable GetDataTable()
{
DataTable table = new DataTable("SomeClassTable");
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Address", typeof(string));
table.Columns.Add("Phone", typeof(string));
return table;
}
}
你可以更进一步,但这应该给你一个很好的选择和一个起点。您可以保留 GetDataTable
函数 public,并使用它来创建您的 table 实例,或者将其设为私有并仅在内部使用。我会选择前者,并在你的函数中使用它来初始化 table ,然后再填充它。您甚至可以摆脱 static
修饰符并将其添加到您的界面中,但我更喜欢在此实例中静态使用它,因为它不依赖于 class 的实例和所涉及的数据, 仅在结构上。
无论哪种方式,您都可以将上面的代码更改为如下所示:
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1");
System.Data.DataTable dataTable = Project1.SomeClass.GetDataTable();
foreach (Project1.SomeClass someClassObject in myList)
{
dataTable.Rows.Add(someClassObject.GetDataRow());
}
如果您需要递增的 id
列,您可以轻松地将其添加到 GetDataTable
/GetDataRow
函数中并像上面那样更新它们。
这只是一个简单的例子,它很可能会被清理和优化一些,但它仍然传达了这个想法。希望对你有所帮助。
我有如下代码(我已经对其进行了泛化和简化以仅代表手头的问题)。该代码有效,即它接收 DataGridView.DataSource
并最终使用 EPPlus
将数据输出到 Excel 文件。我认为我的问题与协方差以及如何使用它有关。
因此您看到它根据在 DataSource
中找到的类型构建 newList
。然后再往下一点,它使用此类型独有的属性 someClassObject.Name, .Address and .Phone
添加数据。
我的问题是大约有 75 种不同的 class 可以通过 DataGridView
参数传入。每个 class 都有自己独特的属性(即不一定是名称、地址、Phone),尽管给定 DataGridView.DataSource
中的所有对象都是相同的 class。
我可以有一个基于 type.FullName
的 giant switch 语句,然后每个语句都有自己的 for 循环来将 属性 值分配给单元格.那会起作用,但会非常麻烦。有更好的方法吗?
public void openExcelReport(ref DataGridView dataGridView, bool bolSave = false, bool bolOpen = true, string pageTitle = "EXPORTED DATA")
{
// put dataGridView.DataSource into a List
object firstItem = null;
var myDataSource = dataGridView.DataSource;
var myList = ((System.Windows.Forms.BindingSource)dataGridView.DataSource).List;
firstItem = ((System.Collections.IList)myList)[0];
var type = firstItem.GetType();
Type PROJECT1_TYPE = typeof(Project1.SomeClass);
Type PROJECT2_TYPE = typeof(Project2.SomeOtherClass); // many more of these
dynamic newList = null;
if (type.FullName.Equals(PROJECT1_TYPE.FullName))
{
newList = new List<Project1.SomeClass>();
foreach (Project1.SomeClass someClassObject in myList)
{
newList.Add(someClassObject);
}
}
ExcelPackage package = new ExcelPackage();
using ((package)) // use EPPlus
{
// Create the worksheet
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1");
// Load the datatable into the sheet, starting from cell A1. Print the column names on row 1
System.Data.DataTable dataTable = new System.Data.DataTable();
dataTable.Columns.Add("Id");
dataTable.Columns.Add("FirstColumn", typeof(string));
dataTable.Columns.Add("SecondColumn", typeof(string));
dataTable.Columns.Add("ThirdColumn", typeof(string));
dataTable.Columns[0].AutoIncrement = true;
var column_id = 0;
foreach (Project1.SomeClass someClassObject in "FirstColumn")
{
DataRow dataRow = dataTable.NewRow();
dataRow["FirstColumn"] = someClassObject.Name;
dataRow["SecondColumn"] = someClassObject.Address;
dataRow["ThirdColumn"] = someClassObject.Phone
dataTable.Rows.Add(dataRow);
column_id += 1;
}
// worksheet is now populated, so save Excel File
...
}
您可以将它移到 class 实现中,而不是在此函数中执行 DataRow
创建,使用通用接口来强制执行它,例如:
public interface DataRowConvertable
{
DataRow GetDataRow();
}
public class SomeClass : DataRowConvertable
{
public SomeClass() { }
public SomeClass(string name, string address, string phone)
{
Name = name;
Address = address;
Phone = phone;
}
public string Name { get; set; }
public string Address { get; set; }
public string Phone { get; set; }
public DataRow GetDataRow()
{
DataRow row = GetDataTable().NewRow();
row["Name"] = this.Name;
row["Address"] = this.Address;
row["Phone"] = this.Phone;
return row;
}
public static DataTable GetDataTable()
{
DataTable table = new DataTable("SomeClassTable");
table.Columns.Add("Name", typeof(string));
table.Columns.Add("Address", typeof(string));
table.Columns.Add("Phone", typeof(string));
return table;
}
}
你可以更进一步,但这应该给你一个很好的选择和一个起点。您可以保留 GetDataTable
函数 public,并使用它来创建您的 table 实例,或者将其设为私有并仅在内部使用。我会选择前者,并在你的函数中使用它来初始化 table ,然后再填充它。您甚至可以摆脱 static
修饰符并将其添加到您的界面中,但我更喜欢在此实例中静态使用它,因为它不依赖于 class 的实例和所涉及的数据, 仅在结构上。
无论哪种方式,您都可以将上面的代码更改为如下所示:
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("Worksheet 1");
System.Data.DataTable dataTable = Project1.SomeClass.GetDataTable();
foreach (Project1.SomeClass someClassObject in myList)
{
dataTable.Rows.Add(someClassObject.GetDataRow());
}
如果您需要递增的 id
列,您可以轻松地将其添加到 GetDataTable
/GetDataRow
函数中并像上面那样更新它们。
这只是一个简单的例子,它很可能会被清理和优化一些,但它仍然传达了这个想法。希望对你有所帮助。