J'ai le code comme ci-dessous (je l'ai générée et réduit pour représenter juste le problème à portée de main). Le code fonctionne, c'est-à-dire qu'il prend un DataGridView.DataSource
et ultimement, en utilisant EPPlus
, affiche les données dans un fichier Excel. Ma question concerne la covariance et comment l'utiliser, je pense.DataGridView avec covariance?
Donc, vous voyez qu'il construit newList
en fonction du type qu'il a trouvé dans le DataSource
. Puis, un peu plus bas, il ajoute les données en utilisant les propriétés, someClassObject.Name, .Address and .Phone
qui sont uniques à ce type.
Mon problème est qu'il y a environ 75 classes différentes qui pourraient être transmises par le paramètre DataGridView
. Chaque classe a ses propres propriétés uniques (c'est-à-dire pas nécessairement le nom, l'adresse, le téléphone) bien que tous les objets donnés dans DataGridView.DataSource
soient de la même classe.
Je pourrais avoir un géant commutateur d'instruction basée sur type.FullName
et puis chacun aurait sa propre boucle pour assigner les valeurs de propriété à la cellule. Cela fonctionnerait mais serait incroyablement lourd. Y a-t-il une meilleure manière de faire cela?
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
...
}
Pour les classes que vous transmettez, pourriez-vous les modifier pour implémenter une interface avec une fonction 'GetDataRow()' (ou quelque chose de similaire) afin que vous puissiez avoir ce code dans la classe elle-même, ici vous faites simplement 'dataTable.Rows.Add (someClassObject.GetDataRow())'. Et être fait avec. Cela vous éviterait d'avoir besoin d'un bloc 'switch' ou' if/else' car les informations pour générer le 'DataRow' sont directement associées à la classe contenant les colonnes potentielles en tant que propriétés. – gmiley