4

我试图映射一个 csv 文件,以便每条记录都只是一个Dictionary<string,object>.

我收到一个

ArgumentException "不是成员访问;"

当我尝试这样做时。代码如下:

public class CsvFileReader : FileReader
{
    public CsvFileReader(string path) : base(path){ }

    public IDictionary<string, object> Read()
    {
        var reader = new CsvReader(new StreamReader(Path));
        reader.Read();
        reader.Configuration.RegisterClassMap(new DictionaryClassMap(reader.FieldHeaders));
        return reader.GetRecord<Dictionary<string, object>>();
    }

    private class DictionaryClassMap : CsvClassMap<Dictionary<string, object>>
    {
        private readonly IEnumerable<string> _headers;

        public DictionaryClassMap(IEnumerable<string> headers)
        {
            _headers = headers;
        }

        public override void CreateMap()
        {
            foreach (var header in _headers)
            {
                var localHeader = header;
                Map(x => x[localHeader]);
            }
        }
    } 
}
4

2 回答 2

12

不幸的是,目前不支持映射到Dictionary.

如果你尝试做GetRecords<Dictionary<string, object>>(),你会得到一个错误。

Types that inhererit 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?

你也不能映射到一个Dictionary。在映射中,您需要为要映射到的字段指定类的属性。索引器不是成员属性,这就是您收到该错误的原因。

解决方案:

你可以做的是:

var record = csv.GetRecord<dynamic>();

您可以将其用作动态对象。

所需的解决方案

在内部,它使用ExpandoObject, 所以你可以这样做。

var dict = csv.GetRecord<dynamic>() as IDictionary<string, object>;
于 2014-04-10T19:42:17.983 回答
1

我试图做类似的事情(尽管没有将所有列都读入Dictionary,只是一些)。所以,如果这是有用的,(并得到这个答案的大力帮助)你可以拥有一个Dictionary作为类的属性,然后填充它(正如乔希所说,你不能自己填充Dictionary它,因为 CsvHelper 期待一个成员要映射到的属性)。

下面将映射到类DictionaryProperty的属性。Dictionary<string,string>MyClassWithDictionaryMapper

public class MyClassWithDictionaryMapper: ClassMap<MyClassWithDictionary>
{
    public MyClassWithDictionaryMapper(List<string> headers)
    {

        Map(m => m.DictionaryProperty).ConvertUsing
           (row => headers.Select
            (column => new { column, value = row.GetField(column) })
            .ToDictionary(d => d.column, d => d.value)
            );
    }
}
于 2020-05-20T22:48:17.273 回答