Création dynamic de colonnes à l’aide de csvHelper

J’ai un ouvrier avec divers champs qui sont récupérés du serveur. J’utilise le package CSVHelper pour convertir cette classe en feuille Excel. Le travailleur a des champs comme:

class Worker { ssortingng name; ssortingng phone; ssortingng age; Dictionary customerField; } 

Je peux mapper le nom, le téléphone, le numéro comme

 class WorkerMap : CsvClassMap { public WorkerMap() { Map(m => m.name); Map(m => m.phone); Map(m => m.age); } } 

Et je génère la carte en:

 csv.Configuration.RegisterClassMap(); 

Rédigez la liste des travailleurs par:

 csv.WriteRecords(workerList); 

Comment mapper le dictionnaire customerField sur la feuille Excel de telle sorte que la clé (chaîne) soit un autre nom de colonne et que la valeur (object) soit la valeur de la colonne.

Est-ce que CSVHelper nous aide à le faire au moment de l’exécution? J’ai parcouru la documentation. Impossible de trouver quelque chose qui a fonctionné pour moi.

Je ne pense pas que l’écriture d’un dictionnaire soit supscope pour le moment. Tout d’abord, CsvHelper aurait du mal à savoir quelles en-têtes écrire. Heureusement, utiliser CsvWriter manuellement, en écrivant un champ à la fois, n’est pas trop complexe. Si nous supposons que chaque utilisateur possède les mêmes clés dans customerField votre code pourrait ressembler à ceci.

 var firstWorker = workerList.First(); var keys = firstWorker.customerField.Keys.ToList(); var headers = new []{ "name", "phone", "age"}.Concat(keys).ToList(); var csv = new CsvWriter( textWriter ); // Write the headers foreach( var header in headers ) { csv.WriteField(header); } csv.NextRecord(); // Write the rows foreach( var item in workerList) { csv.WriteField(item.name); csv.WriteField(item.phone); csv.WriteField(item.age); var dict = worker.customerField; foreach (var key in keys) { csv.WriteField(dict[key]); } csv.NextRecord(); } 

Ce code n’a pas été testé, mais devrait vous rapprocher du comportement dont vous avez besoin. Si les clés du dictionnaire customerField ne sont pas cohérentes dans la liste, le code serait un peu plus compliqué, mais il rest résolu.

Le dictionnaire n’est pas pris en charge, mais ExpandoObject est pris en charge.

https://github.com/JoshClose/CsvHelper/blob/48e70742e06007dae3a635c418b7e3358f667c4f/src/CsvHelper.Tests/Writing/MultipleHeadersTest.cs

https://github.com/JoshClose/CsvHelper/blob/b74a2f95a101158f4cdedd25fae6e8392b58855b/src/CsvHelper.Tests/Writing/DynamicTests.cs

Si vous suivez le premier lien ci-dessus, vous trouverez la méthode WriteDynamicHeader utilisée sur les lignes 50 et 57.

Avec l’aide d’une méthode d’extension, je crée un ExpandoObject pour chaque enregistrement et utilise CsvHelper pour écrire cet object.Le paramètre Dictionary nommé document est celui avec lequel je souhaite créer l’enregistrement CSV.

 public static class DictionaryCsvExtentions { public static dynamic BuildCsvObject(this Dictionary document) { dynamic csvObj = new ExpandoObject(); foreach (var p in document) { AddProperty(csvObj, p.Key, p.Value); } return csvObj; } private static void AddProperty(ExpandoObject expando, ssortingng propertyName, object propertyValue) { var expandoDict = expando as IDictionary; if (expandoDict.ContainsKey(propertyName)) { expandoDict[propertyName] = propertyValue; } else { expandoDict.Add(propertyName, propertyValue); } } } 

Maintenant, je peux créer un ExpandoObject à partir de mon dictionnaire comme ceci

 var csvObj = myDictonary.BuildCsvObject(); 

et avec cela, après les tests de Josh dans le lien ci-dessus, nous avons tout ce dont nous avons besoin pour utiliser un dictionnaire de manière assez transparente avec CsvHelper. Je ne pense pas que ce soit une meilleure solution pour Michael, mais une approche différente.

crédit où crédit est dû à la base ExpandoObject du code de dictionnaire (à partir duquel il existe beaucoup plus d’explications!) https://www.oreilly.com/learning/building-c-objects-dynamically