我有一个字典列表,其键列表相同,但值不同。有没有办法使用 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?'
}
}
有什么办法可以解决吗?
谢谢!
我相信唯一的方法就是用手写下来。
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();
}
}
假设您有字典
// 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");
}
简单的方法是编写自定义转换器
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);
}
文档在这里