Creación dinámica de columnas usando csvHelper

Creación dinámica de columnas usando csvHelper

No creo que escribir un diccionario sea compatible en este momento. Por un lado, CsvHelper tendría dificultades para saber qué encabezados escribir. Afortunadamente, no es demasiado complejo usar CsvWriter manualmente, escribiendo un campo a la vez. Si asumimos que cada Worker tiene las mismas claves en customerField entonces su código podría verse así.

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

Este código no ha sido probado, pero debería acercarte bastante al comportamiento que necesitas. Si el customerField las claves del diccionario no son consistentes en la lista, entonces el código sería un poco más complicado pero aún se puede resolver.


No se admite el diccionario, pero se admite ExpandoObject.

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 sigue el primer enlace anterior, encontrará el método WriteDynamicHeader en uso en las líneas 50 y 57.

Con la ayuda de un método de extensión, creo un ExpandoObject para cada registro y uso CsvHelper para escribir ese objeto. El Dictionary<string, object> parámetro llamado document es desde lo que deseo crear el registro CSV.

public static class DictionaryCsvExtentions
{
    public static dynamic BuildCsvObject(this Dictionary<string, object> document)
    {
        dynamic csvObj = new ExpandoObject();

        foreach (var p in document)
        {
            AddProperty(csvObj, p.Key, p.Value);
        }

        return csvObj;
    }

    private static void AddProperty(ExpandoObject expando, string propertyName, object propertyValue)
    {
        var expandoDict = expando as IDictionary<string, object>;
        if (expandoDict.ContainsKey(propertyName))
        {
            expandoDict[propertyName] = propertyValue;
        }
        else
        {
            expandoDict.Add(propertyName, propertyValue);
        }
    }
}

Ahora puedo crear un ExpandoObject desde mi diccionario como este

var csvObj = myDictonary.BuildCsvObject();

y con eso, siguiendo las pruebas de Josh en el enlace anterior, tenemos todo lo que necesitamos para usar un diccionario sin problemas con CsvHelper. No creo que esta sea una solución mejor que la de Michael, solo un enfoque diferente.

crédito donde se debe crédito el ExpandoObject básico del código del diccionario es de aquí (¡donde hay mucha más explicación!) https://www.oreilly.com/learning/building-c-objects-dynamically