Написание класса с вложенным словарем для csv с использованием csvhelper, а также с использованием карты - PullRequest
0 голосов
/ 01 ноября 2019

Я использую csvhelper, чтобы попытаться экспортировать коллекцию элементов, которая содержит вложенный словарь, в csv.

Мне также нужно изменить имена заголовков в зависимости от текущей культуры. Мне удалось выполнить перевод заголовка с помощью сопоставления, показанного ниже, поэтому я должен иметь возможность сохранить эту функциональность, в то же время поддерживая вложенный словарь.

CultureInfo currentCulture = localeCode == null ? CultureInfo.CurrentCulture : new CultureInfo(localeCode);
var rm = new ResourceManager("fileName", Assembly.GetExecutingAssembly());

Map(m => m.Id).Name(rm.GetString("Id", currentCulture));
Map(m => m.Name).Name(rm.GetString("Name", currentCulture));

Я пытался использовать ExpandoObjects, и это, похоже,работать, однако мне интересно, есть ли более элегантное решение.

// distinct list of all keys in the dictionary
var customAttributeNames = collection.SelectMany(c => c.CustomAttributes.Keys).Distinct().ToList();
var records = new List<dynamic>();
    foreach (var item in collection)
    {
        IDictionary<string, object> record = new ExpandoObject();
        record["Id"] = item.Id;
        record["Name"] = item.Name;

        // This is the nested dictionary 
        foreach (var name in customAttributeNames)
        {
            item.CustomAttributes.TryGetValue(name, out var value);
            record.Add(name, value);
        }
        records.Add(record);
    }

    using (var writer = new StringWriter())
    using (var csv = new CsvWriter(writer))
    {
        csv.WriteRecords(records);
    }

1 Ответ

0 голосов
/ 01 ноября 2019

Почему бы не попробовать JsonFormatter для свойства. Этот простой пример отлично работает

public class MyClass
{
    public int Number { get; set; }
    public Dictionary<string, string> Value { get; set; }
}

public class JsonConverter : ITypeConverter
{
    public string ConvertToString(object value, IWriterRow row, MemberMapData memberMapData)
    {
        return JsonConvert.SerializeObject(value);
    }

    public object ConvertFromString(string text, IReaderRow row, MemberMapData memberMapData)
    {
        return JsonConvert.DeserializeObject<Dictionary<string, string>>(text);
    }
}

public class MyClassMap : ClassMap<MyClass>
{
    public MyClassMap()
    {
        var i = 0;
        Map(m => m.Number).Index(i++);
        Map(m => m.Value).Index(i++).TypeConverter<JsonConverter>();
    }
}

class Program
{
    static void Main(string[] args)
    {
        var list = Enumerable.Range(0, 5).Select(x => new MyClass()
        {
            Number = x,
            Value = new Dictionary<string, string>()
            {
                {x.ToString(), x + 1.ToString()}
            }
        });
        using (var writer = new StringWriter())
        using (var csv = new CsvWriter(writer)
        {
            Configuration = { HasHeaderRecord = true },

        })
        {
            csv.Configuration.RegisterClassMap<MyClassMap>();
            csv.WriteRecords(list);
            writer.Flush();
            Console.WriteLine(writer.ToString());
        }

    }
}
...