CSVHelper - 能否写入字典列表?

5

我有一个字典列表,拥有相同的键但不同的值。是否可以使用CSVHelper将其写入CSV文件中? 我已经有以下示例代码,但显然它没有起作用。

       static void Main(string[] args)
        {

            List<Dictionary<String, String>> records = new List<Dictionary<string, string>>();
            Dictionary<String, String> data1 = new Dictionary<String, String>();
            data1.Add("Name1", "Value1");
            data1.Add("Name2", "Value2");
            records.Add(data1);

            Dictionary<String, String> data2 = new Dictionary<String, String>();
            data2.Add("Name1", "Value1");
            data2.Add("Name2", "Value2");
            records.Add(data2);

            using (var writer = new StreamWriter("e:\\temp\\test.csv"))
            using (var csv = new CsvWriter(writer))
            {

                csv.WriteRecords(records);
//GEtting exception here
//CsvHelper.Configuration.CsvConfigurationException: 'Types that inherit IEnumerable cannot be auto mapped. Did you accidentally call GetRecord or WriteRecord which acts on a single record instead of calling GetRecords or WriteRecords which acts on a list of records?'

            }
        }

有没有什么解决方法?

谢谢!

3个回答

10

我相信唯一的方法就是手写它们。

using (var writer = new StreamWriter("e:\\temp\\test.csv"))
using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
{
    var headings = new List<string>(records.First().Keys);

    foreach (var heading in headings)
    {
        csv.WriteField(heading);
    }

    csv.NextRecord();

    foreach (var item in records)
    {
        foreach (var heading in headings)
        {
            csv.WriteField(item[heading]);
        }

        csv.NextRecord();
    }
}


0
假设你有一个Dictionary。 键是你的标题名称,而string[]是标题下的值。
// Class to convert to CSV
public class LDAPRoles
    {
        public string[] LendingUser { get; set; }
        public string[] LendingUserViewOnly { get; set; }
        public string[] CreditManagement { get; set; }
        public string[] AssistantBranchManager { get; set; }
        public string[] BranchManager { get; set; }
        public string[] CreditStaff { get; set; }
        public string[] FraudStaff { get; set; }
        public string[] DistrictManager { get; set; }
        public string[] DigitalAdvisor { get; set; }
    }

在我的控制器中:
public IActionResult DownloadRoles()
        {
            // Get proprties from class
            var propertyInfos = _ldapOptions.Roles
                .GetType()
                .GetProperties();

            // Get header names from properties
            var headerNames = propertyInfos.Select(p => p.Name)
                .ToArray();

            // Create dictionary
            var dictionary = new Dictionary<string, string[]>();
            foreach (var header in headerNames)
            {
                foreach (var prop in propertyInfos)
                {
                    if (prop.Name == header)
                    {
                        var values = (string[])prop.GetValue(_ldapOptions.Roles);
                        dictionary.Add(header, values);
                    }
                }
            }

            // Calculate max rows
            var maxRows = dictionary.Max(c => c.Value.Length);

            // Write to temp file
            var file = Path.GetTempFileName();
            using (var writer = new StreamWriter(file))
            using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
            {
                // Headers
                foreach (var heading in headerNames)
                {
                    csv.WriteField(heading);
                }

                csv.NextRecord();

                // Insert Rows
                for (int i = 0; i < maxRows; i++)
                {
                    foreach (var heading in headerNames)
                    {
                        var values = dictionary[heading];
                        if (i > values.Length - 1)
                        {
                            // empty row
                            csv.WriteField("");
                        }
                        else
                        {
                            // write value
                            csv.WriteField(values[i]);
                        }
                    }

                    // Next record
                    csv.NextRecord();
                }
            }

            // Read the stream as a string, and write the string to the console.
            string csvText;
            using (var sr = new StreamReader(file))
            {
                csvText = sr.ReadToEnd();
            }

            var csvBytes = Encoding.ASCII.GetBytes(csvText);

            // delete temp file
            System.IO.File.Delete(file);

            Response.Headers.Add("Content-Disposition", $"attachment; filename=\"Roles.csv\"");

            return File(csvBytes, "text/csv", $"Roles.csv");
        }

0
简单的方法是编写自定义转换器。
public class DictionaryConverter : DefaultTypeConverter
{
    public override string? ConvertToString(object? value, IWriterRow row, MemberMapData memberMapData)
    {
        if (value is Dictionary<string, int> dictionary)
        {
            foreach (var item in dictionary)
            {
                row.WriteField(item.Value);
            }
            
        }
        return null;
    }
}

注册
  Map(s => s.MyDistionary).TypeConverter<DictionaryConverter>();

这个缺陷仍然需要使用“丑陋”的代码来处理标题。
var headings = new List<string>(records.First().Keys);

foreach (var heading in headings)
{
    csv.WriteField(heading);
}

Doc is here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接