Mapping to a Dictionary

情到浓时终转凉″ 提交于 2020-07-09 03:49:45

问题


I was trying to map a csv file so that each record would simply be a Dictionary<string,object>.

I am receiving an

ArgumentException "Not a member access;"

When I try to do this. Code included below:

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

回答1:


Unfortunately, there currently is no support for mapping to a Dictionary.

If you try doing GetRecords<Dictionary<string, object>>(), you will get an error.

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?

You can't map to a Dictionary either. In a mapping you need to specify a property of the class for the field to be mapped to. The indexer is not a member property which is why you're getting that error.

SOLUTION:

What you CAN do is this:

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

You can use it as a dynamic object.

DESIRED SOLUTION

Internally, it uses the ExpandoObject, so you can do this.

var dict = csv.GetRecord<dynamic>() as IDictionary<string, object>;



回答2:


I was trying to do similar (although not reading all the columns into the Dictionary, just some). So, in case this is of use, (and strongly aided by this answer) you can have a Dictionary as a property of a class and then populate that (as Josh say's you can't populate a Dictionary on it's own as CsvHelper is expecting a member property to map to).

The below would map to a property DictionaryProperty which is a Dictionary<string,string> of the class 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)
            );
    }
}


来源:https://stackoverflow.com/questions/21311423/mapping-to-a-dictionary

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!