From 15afea1b9ac942a0638d7552153267682f9d5776 Mon Sep 17 00:00:00 2001 From: Rahul Khera Date: Mon, 8 Aug 2016 12:08:10 +1000 Subject: [PATCH 1/2] Added code for supplying field name headings at runtime using a dictionary. This is still a naive implementation, and needs to be much more type safe in the future. --- LINQtoCSV/CsvContext.cs | 14 ++++++++++++-- LINQtoCSV/FieldMapper.cs | 12 +++++++++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/LINQtoCSV/CsvContext.cs b/LINQtoCSV/CsvContext.cs index 62d799c..0bc681c 100644 --- a/LINQtoCSV/CsvContext.cs +++ b/LINQtoCSV/CsvContext.cs @@ -30,9 +30,18 @@ public class CsvContext /// /// Additional information how the input file is to be interpreted, such as the culture of the input dates. /// + /// Runtime overrides for field names in the CSV file /// /// Values read from the stream or file. /// + public IEnumerable Read(string fileName, CsvFileDescription fileDescription, Dictionary fieldNameOverrides) where T : class, new() + { + // Note that ReadData will not be called right away, but when the returned + // IEnumerable actually gets accessed. + + IEnumerable ie = ReadData(fileName, null, fileDescription, fieldNameOverrides); + return ie; + } public IEnumerable Read(string fileName, CsvFileDescription fileDescription) where T : class, new() { // Note that ReadData will not be called right away, but when the returned @@ -81,7 +90,8 @@ public class CsvContext private IEnumerable ReadData( string fileName, StreamReader stream, - CsvFileDescription fileDescription) where T : class, new() + CsvFileDescription fileDescription, + Dictionary fieldNameOverrides = null) where T : class, new() { // If T implements IDataRow, then we're reading raw data rows bool readingRawDataRows = typeof(IDataRow).IsAssignableFrom(typeof(T)); @@ -169,7 +179,7 @@ private IEnumerable ReadData( if (firstRow && fileDescription.FirstLineHasColumnNames) { - if (!readingRawDataRows) { fm.ReadNames(row); } + if (!readingRawDataRows) { fm.ReadNames(row, fieldNameOverrides); } } else { diff --git a/LINQtoCSV/FieldMapper.cs b/LINQtoCSV/FieldMapper.cs index 9ef9dfc..3a51a66 100644 --- a/LINQtoCSV/FieldMapper.cs +++ b/LINQtoCSV/FieldMapper.cs @@ -398,7 +398,7 @@ public FieldMapper_Reading( /// /// /// - public void ReadNames(IDataRow row) + public void ReadNames(IDataRow row, Dictionary fieldNameOverrides = null) { // It is now the order of the field names that determines // the order of the elements in m_IndexToInfo, instead of @@ -410,7 +410,7 @@ public void ReadNames(IDataRow row) int currentNameIndex = 0; for (int i = 0; i < row.Count; i++) { - if (!m_NameToInfo.ContainsKey(row[i].Value)) { + if (string.IsNullOrEmpty(row[i].Value) || !(m_NameToInfo.ContainsKey(row[i].Value) || (fieldNameOverrides != null && fieldNameOverrides.ContainsKey(row[i].Value) && m_NameToInfo.ContainsKey(fieldNameOverrides[row[i].Value])))) { //If we have to ignore this column if (m_fileDescription.IgnoreUnknownColumns) { continue; @@ -433,7 +433,13 @@ public void ReadNames(IDataRow row) continue; } - m_IndexToInfo[_mappingIndexes[i]] = m_NameToInfo[row[i].Value]; + if (fieldNameOverrides == null || !fieldNameOverrides.ContainsKey(row[i].Value)) + m_IndexToInfo[_mappingIndexes[i]] = m_NameToInfo[row[i].Value]; + else + { + m_IndexToInfo[_mappingIndexes[i]] = m_NameToInfo[fieldNameOverrides[row[i].Value]]; + } + if (m_fileDescription.EnforceCsvColumnAttribute && (!m_IndexToInfo[i].hasColumnAttribute)) { // enforcing column attr, but this field/prop has no column attr. From 4c758382698fe6bf15f43538864c32083cda4d30 Mon Sep 17 00:00:00 2001 From: Rahul Khera Date: Mon, 8 Aug 2016 12:47:07 +1000 Subject: [PATCH 2/2] Added test code for the new runtime field mappings --- TestConsoleApplication/ProductDataDto.cs | 13 ++++++++++++ TestConsoleApplication/Program.cs | 20 +++++++++++++++++++ .../TestConsoleApplication.csproj | 1 + 3 files changed, 34 insertions(+) create mode 100644 TestConsoleApplication/ProductDataDto.cs diff --git a/TestConsoleApplication/ProductDataDto.cs b/TestConsoleApplication/ProductDataDto.cs new file mode 100644 index 0000000..68b2c5c --- /dev/null +++ b/TestConsoleApplication/ProductDataDto.cs @@ -0,0 +1,13 @@ +namespace TestConsoleApplication +{ + public class ProductDataDto + { + public string Name { get; set; } + + public string ShopsAvailable { get; set; } + + public string HexProductCode { get; set; } + + public string Description { get; set; } + } +} \ No newline at end of file diff --git a/TestConsoleApplication/Program.cs b/TestConsoleApplication/Program.cs index e82ff17..1181c71 100644 --- a/TestConsoleApplication/Program.cs +++ b/TestConsoleApplication/Program.cs @@ -34,6 +34,26 @@ static void Main(string[] args) try { + var productFieldOverrides = new Dictionary() + { + { "name", "Name" }, + { "shopsAvailable", "ShopsAvailable" }, + { "code", "HexProductCode" }, + { "description", "Description" }, + }; + + fileDescription_namesUs.IgnoreUnknownColumns = true; + + var productDtos = cc.Read("../../TestFiles/goodfile_us.csv", fileDescription_namesUs, + productFieldOverrides); + + foreach (var productDataDto in productDtos) + { + Console.WriteLine($"{productDataDto.Name}, {productDataDto.Description}, {productDataDto.HexProductCode}, {productDataDto.ShopsAvailable}"); + } + + fileDescription_namesUs.IgnoreUnknownColumns = false; + dataRows_namesUs = cc.Read("../../TestFiles/goodfile_us.csv", fileDescription_namesUs); diff --git a/TestConsoleApplication/TestConsoleApplication.csproj b/TestConsoleApplication/TestConsoleApplication.csproj index a735f28..6673795 100644 --- a/TestConsoleApplication/TestConsoleApplication.csproj +++ b/TestConsoleApplication/TestConsoleApplication.csproj @@ -77,6 +77,7 @@ +