So I'll explain my situation first. I have a WPF View for my customer that is populated based on SQL strings that the customer defines. They can change these and add/remove these at any point and the structure of the result set is not in my control. My expected output for this is
- Populating the DataGrid at runtime without prior knowledge of the structure so using AutoGenerateColumns and providing dataTable.DefaultView as the ItemsSource for the DataGrid. This is bound to my DataGrid.
 
GetItemsSource = dataTable.DefaultView;
- Export this DataGrid to a CSV for the customer to check whenever they want.
 
Now I already have a Generic List function to Save to CSV but since the structure is not known I can't change my dataTable to a list to use this.
My current solution is Save To CSV function that uses a dataTable instead of a List.
Is there some other type of data structure I could use instead of dataTable that would make using my generic function possible or do I have just have an extra Save To CSV function just for this scenario?
UPDATE
My generic list function
public static void SaveToCsv<T>(List<T> data, string filePath) where T : class
        {
            CreateDirectoryIfNotExists(filePath);
            List<string> lines = new();
            StringBuilder line = new();
            if (data == null || data.Count == 0)
            {
                throw new ArgumentNullException("data", "You must populate the data parameter with at least one value.");
            }
            var cols = data[0].GetType().GetProperties();
            foreach (var col in cols)
            {
                line.Append(col.Name);
                line.Append(",");
            }
            lines.Add(line.ToString().Substring(0, line.Length - 1));
            foreach (var row in data)
            {
                line = new StringBuilder();
                foreach (var col in cols)
                {
                    line.Append(col.GetValue(row));
                    line.Append(",");
                }
                lines.Add(line.ToString().Substring(0, line.Length - 1));
            }
            System.IO.File.WriteAllLines(filePath, lines);
        }
My current Data Table function
public static void SaveToCsv(DataTable data, string filePath)
        {
            CreateDirectoryIfNotExists(filePath);
            List<string> lines = new();
            StringBuilder line = new();
            if(data == null)
            {
                throw new ArgumentNullException("data", "The DataTable has no values to Save to CSV.");
            }
            IEnumerable<string> columnNames = data.Columns.Cast<DataColumn>().Select(column => column.ColumnName);
            line.AppendLine(string.Join(",", columnNames));
            lines.Add(line.ToString().Substring(0, line.Length - 3));
            int prevlinelength = line.Length - 1;
            foreach (DataRow row in data.Rows)
            {
                IEnumerable<string> fields = row.ItemArray.Select(field => field.ToString());
                line.AppendLine(string.Join(",", fields));
                lines.Add(line.ToString().Substring(prevlinelength + 1, line.Length - 3 - prevlinelength));
                prevlinelength = line.Length - 1;
            }
            File.WriteAllLines(filePath, lines);
        }