質問

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]);
            }
        }
    } 
}
役に立ちましたか?

解決

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>;

他のヒント

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)
            );
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top