Csvhelper: WriteRecords uses wrong type map when writing a derived type

Created on 7 Sep 2016  Â·  7Comments  Â·  Source: JoshClose/CsvHelper

v2.16.1.0

When using WriteRecords to write an enumerable of <DerivedFromT>, the code to determine the type seems to incorrectly picks up the base class (and therefore CsvMap) <T>,

public class MyBaseType{}
public class MyDerivedType : MyBaseType{}

var records = new List<MyDerivedType>{ blah, blah }

var csv = myCsvWriter.WriteRecords(records);

The results from WriteRecords appears to have used the CsvMap for MyBaseType and not the map for MyDerviedType. I've not had time to pull in your code to debug through it yet, but it seems like the code in WriteRecords(IEnumerable records) will incorrectly calculate the type as the base type.

bug

All 7 comments

Why are you mapping both and not just MyDerivedType?

Can't speak for him, but for my apps, CSV configuration is a singleton (via
my IoC container) and all of my Class Maps are registered and injected into
the configuration. If I had a class and its derived type both registered
and mapped, this strategy would fail due to this issue.

On Sep 9, 2016 1:18 PM, "Josh Close" [email protected] wrote:

Why are you mapping both and not just MyDerivedType?

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/JoshClose/CsvHelper/issues/570#issuecomment-245979003,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AD_ohbGMOx5KVauo8ZyIec515KvUVMUJks5qoZTQgaJpZM4J3CQN
.

I export lists of either MyBaseType or MyDerivedType as csv files depending on the user's export settings. Essentially both types are rows in exportable reports, with MyDerviedType having extra details if required.

I register the maps and CsvWriter at application startup using dependency injection, so at report export time both maps have already been registered.

Does this issue happen when reading or is it only writing?

I'll take a look at the issue tonight.

We only output csv so I haven't tried to recreate with a read. From looking at the source code I think line 455 in CsvWriter may be the issue?

var genericEnumerable = records.GetType().GetInterfaces().FirstOrDefault( t => t.GetTypeInfo().IsGenericType && t.GetGenericTypeDefinition() == typeof( IEnumerable<> ) );

I've not had a chance to check out the CsvHelper code to run against, but it looks like maybe that line could be pulling out the base type rather than the derived type when calling FirstOrDefault on the list of types?

This is where the issue lies. https://github.com/JoshClose/CsvHelper/blob/2.16.2/src/CsvHelper/Configuration/CsvClassMapCollection.cs#L32

I will need to loop through the types inheritance chain instead.

If you register the child map before the parent map, it will work the way you want. I'll fix it to look up the chain instead though.

Fixed in NuGet version 2.16.3

Was this page helpful?
0 / 5 - 0 ratings