The goal here is that after inputing csv file, a magic tool would output c# class with the fields from csv. Let's look at example.
Input myFile.csv:
Year,Make,Model
1997,Ford,E350
2000,Mercury,Cougar
Output myFile.cs
public class myFile
{
public string Year;
public string Make;
public string Model;
}
So, the only thing I would need to fix is the types of properties. After that I would use this class with FileHelpers to read csv file. Later it would be mapped to EntityFramework class (using AutoMapper) and saved to database.
Actually, https://csv2entity.codeplex.com/ looks like is doing what I need, but it just doesn't work - I installed it and nothing changed in my Visual studio, no new template appeared. The project is totally dead. Opened source code and ... decided maybe I'll just ask this question in stackoverflow :)
FileHelpers has only a simple wizard, which allows you to manually add fields. But I have 50 fields and this is not the last time I will need to do it, so automated solution is preferred here.
I believe this problem is solved many times before, any help?
Code generation from the Wolfram Language involves converting programs written in the Wolfram Language into other languages and then supporting them so that they can be executed. The Wolfram System compiler provides a system for code generation into the C language.
MATLAB Coder generates readable and portable C code from your MATLAB algorithms. This automated approach speeds up your design workflow and eliminates coding errors introduced by a manual translation process.
Use any C/C++ compiler to compile and run your generated code on any hardware, from desktop systems to mobile devices to embedded hardware. The generated code is royalty-free—deploy it in commercial applications to your customers at no charge.
coder. ceval( cfun_name ) executes the external C/C++ function specified by cfun_name . Define cfun_name in an external C/C++ source file or library. Provide the external source, library, and header files to the code generator. example.
Thank you Bedford, I took your code and added three things:
Final code:
public class CsvToClass
{
public static string CSharpClassCodeFromCsvFile(string filePath, string delimiter = ",",
string classAttribute = "", string propertyAttribute = "")
{
if (string.IsNullOrWhiteSpace(propertyAttribute) == false)
propertyAttribute += "\n\t";
if (string.IsNullOrWhiteSpace(propertyAttribute) == false)
classAttribute += "\n";
string[] lines = File.ReadAllLines(filePath);
string[] columnNames = lines.First().Split(',').Select(str => str.Trim()).ToArray();
string[] data = lines.Skip(1).ToArray();
string className = Path.GetFileNameWithoutExtension(filePath);
// use StringBuilder for better performance
string code = String.Format("{0}public class {1} {{ \n", classAttribute, className);
for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++)
{
var columnName = Regex.Replace(columnNames[columnIndex], @"[\s\.]", string.Empty, RegexOptions.IgnoreCase);
if (string.IsNullOrEmpty(columnName))
columnName = "Column" + (columnIndex + 1);
code += "\t" + GetVariableDeclaration(data, columnIndex, columnName, propertyAttribute) + "\n\n";
}
code += "}\n";
return code;
}
public static string GetVariableDeclaration(string[] data, int columnIndex, string columnName, string attribute = null)
{
string[] columnValues = data.Select(line => line.Split(',')[columnIndex].Trim()).ToArray();
string typeAsString;
if (AllDateTimeValues(columnValues))
{
typeAsString = "DateTime";
}
else if (AllIntValues(columnValues))
{
typeAsString = "int";
}
else if (AllDoubleValues(columnValues))
{
typeAsString = "double";
}
else
{
typeAsString = "string";
}
string declaration = String.Format("{0}public {1} {2} {{ get; set; }}", attribute, typeAsString, columnName);
return declaration;
}
public static bool AllDoubleValues(string[] values)
{
double d;
return values.All(val => double.TryParse(val, out d));
}
public static bool AllIntValues(string[] values)
{
int d;
return values.All(val => int.TryParse(val, out d));
}
public static bool AllDateTimeValues(string[] values)
{
DateTime d;
return values.All(val => DateTime.TryParse(val, out d));
}
// add other types if you need...
}
Usage example:
class Program
{
static void Main(string[] args)
{
var cSharpClass = CsvToClass.CSharpClassCodeFromCsvFile(@"YourFilePath.csv", ",", "[DelimitedRecord(\",\")]", "[FieldOptional()]");
File.WriteAllText(@"OutPutPath.cs", cSharpClass);
}
}
There is a link to full code and working example https://github.com/povilaspanavas/CsvToCSharpClass
You can generate the class code with a little C# app which checks all the values for each column. You can determine which is the narrowest type each one fits:
public static string CSharpClassCodeFromCsvFile(string filePath)
{
string[] lines = File.ReadAllLines(filePath);
string[] columnNames = lines.First().Split(',').Select(str => str.Trim()).ToArray();
string[] data = lines.Skip(1).ToArray();
string className = Path.GetFileNameWithoutExtension(filePath);
// use StringBuilder for better performance
string code = String.Format("public class {0} {{ \n", className);
for (int columnIndex = 0; columnIndex < columnNames.Length; columnIndex++)
{
code += "\t" + GetVariableDeclaration(data, columnIndex, columnNames[columnIndex]) + "\n";
}
code += "}\n";
return code;
}
public static string GetVariableDeclaration(string[] data, int columnIndex, string columnName)
{
string[] columnValues = data.Select(line => line.Split(',')[columnIndex].Trim()).ToArray();
string typeAsString;
if (AllDateTimeValues(columnValues))
{
typeAsString = "DateTime";
}
else if (AllIntValues(columnValues))
{
typeAsString = "int";
}
else if (AllDoubleValues(columnValues))
{
typeAsString = "double";
}
else
{
typeAsString = "string";
}
string declaration = String.Format("public {0} {1} {{ get; set; }}", typeAsString, columnName);
return declaration;
}
public static bool AllDoubleValues(string[] values)
{
double d;
return values.All(val => double.TryParse(val, out d));
}
public static bool AllIntValues(string[] values)
{
int d;
return values.All(val => int.TryParse(val, out d));
}
public static bool AllDateTimeValues(string[] values)
{
DateTime d;
return values.All(val => DateTime.TryParse(val, out d));
}
// add other types if you need...
You can create a command line application from this which can be used in an automated solution.
You can create the dynamic model class from CSV using dynamic in C#. Override TryGetMember of the custom DynamicObject class and use Indexers.
A useful link: C# Linq to CSV Dynamic Object runtime column name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With