I have the following class to create objects from a delimited line:
public class Mapper<T>
{
public T Map(string line, char delimiter)
{
if(String.IsNullOrEmpty(line))
throw new ArgumentNullException(nameof(line));
if (Char.IsWhiteSpace(delimiter))
throw new ArgumentException(nameof(delimiter));
var splitString = line.Split(delimiter);
var properties = typeof(T).GetProperties();
if(properties.Count() != splitString.Count())
throw new InvalidOperationException($"Row has {splitString.Count()} columns but object has {properties.Count()}.");
var obj = Activator.CreateInstance<T>();
for (var i = 0; i < splitString.Count(); i++)
{
var prop = properties[i];
var propType = prop.PropertyType;
var valType = Convert.ChangeType(splitString[i], propType);
prop.SetValue(obj, valType);
}
return (T)obj;
}
}
If I call the map method with a delimited string it will populate all of the properties on the object with the delimited values from the line.
However when I call this from the following:
public class CsvStreamReader<T>
{
private readonly Mapper<T> _mapper;
public CsvStreamReader(Mapper<T> mapper)
{
_mapper = mapper;
}
public IEnumerable<T> ReadCsvFile(string filePath, bool hasHeader)
{
if(hasHeader)
return File.ReadAllLines(filePath)
.Skip(1)
.Select(x => _mapper.Map(x, ','));
return File.ReadAllLines(filePath)
.Select(x => _mapper.Map(x, ','));
}
}
It will return a list of T but all of the properties will be null and won't have been set.
Update: Just realised my class wasn't a class but was actually a struct.