diff --git a/AlphaCSV/CSVParser.cs b/AlphaCSV/CSVParser.cs
index c17f760..fd60133 100644
--- a/AlphaCSV/CSVParser.cs
+++ b/AlphaCSV/CSVParser.cs
@@ -163,6 +163,15 @@ public DataTable ParseDefinedCSV(DataTable schema, string path, CSVParseOptions
return table;
}
+ ///
+ /// Parses a CSV file containing values for the public set properties of the specified type
+ ///
+ /// The type that we will receive
+ /// The path of the CSV File
+ /// CSV Parsing options
+ /// Validation Patterns
+ ///
+ ///
public List ParseType(string path, CSVParseOptions options = null, List validationPatterns = null) {
Type genType = typeof(T);
ConstructorInfo constructor = genType.GetConstructor(new Type[] { });
@@ -185,18 +194,26 @@ public List ParseType(string path, CSVParseOptions options = null, List result = new List(table.Rows.Count);
foreach (DataRow row in table.Rows) {
object GenericInstance = constructor.Invoke(null);
- for (int i = 0; i < propertySetMethods.Count; i++) {
- propertySetMethods[i].Invoke(GenericInstance, new object[] { row[i] });
+ for (int i = 0; i < table.Columns.Count; i++) {
+ string name = table.Columns[i].ColumnName;
+ //We cannot be sure that the CSV field order is correct especially when dealing with derived classes.
+ //Thus we need to read the file first and then correlate the column name to the field of the class that we
+ //need to instantiate.
+ int indexToUse = propertNames.IndexOf(name);
+ if (indexToUse == -1) {
+ throw new InvalidOperationException($"There is no property with name {name}");
+ }
+ object covertedValue = Convert.ChangeType(row[i], propertyTypes[indexToUse]);
+ propertySetMethods[indexToUse].Invoke(GenericInstance, new object[] { covertedValue });
}
result.Add((T)GenericInstance);
}
diff --git a/TestAlphaCSV/CSVReaderTests.ClassParsing.cs b/TestAlphaCSV/CSVReaderTests.ClassParsing.cs
index 291a9f9..a5f4557 100644
--- a/TestAlphaCSV/CSVReaderTests.ClassParsing.cs
+++ b/TestAlphaCSV/CSVReaderTests.ClassParsing.cs
@@ -15,6 +15,11 @@ public record TestRecord {
public string Surname { get; set; }
}
+ public record DerivedRecord : TestRecord {
+ public string FatherName { get; set; }
+ }
+
+
[TestMethod]
public void TestSimpleClassParsing() {
@@ -39,6 +44,34 @@ public void TestSimpleClassParsing() {
List actual = parser.ParseType(path);
+ //Assert
+ CollectionAssert.AreEqual(expected, actual);
+ }
+
+ [TestMethod]
+ public void TestDerivedClass() {
+ string input = "Name,Surname,FatherName\nJohn,Doe,Donald\n";
+
+ //Arrange
+ MockFileSystem fs = new MockFileSystem();
+ MockFileData mockInputFile = new MockFileData(input);
+ string path = @"C:\test.csv";
+ fs.AddFile(path, mockInputFile);
+
+ DerivedRecord rc = new DerivedRecord {
+ Name = "John",
+ Surname = "Doe",
+ FatherName = "Donald"
+ };
+ List expected = new List { rc };
+
+
+ //Act
+ CSVParser parser = new CSVParser(fs); //Inject dependency here
+ //Since we have the expected result we just clone the schema instead of building it by hand.
+ List actual = parser.ParseType(path);
+
+
//Assert
CollectionAssert.AreEqual(expected, actual);
}