Get collection of objects from CSV string and vise-versa A generic class to get object collection from csv string. I would like to know if there's any better way? 

Converter class

public class CsvConverter&lt;T&gt;:List&lt;T&gt; where T:class
{
    private readonly string _csvText;
    private readonly string _separetor;

    /// &lt;summary&gt;
    /// Get object collection from CSV string
    /// &lt;/summary&gt;
    /// &lt;param name="csvText"&gt;CSV string with Title&lt;/param&gt;
    /// &lt;param name="separator"&gt;CSV line separator&lt;/param&gt;
    public CsvConverter(string csvText, string separator= "\r\n")
    {
        this._csvText = csvText;
        _separetor = separator;
        BuildObject();
    }

    /// &lt;summary&gt;
    /// Get CSV string from collection of objects
    /// &lt;/summary&gt;
    /// &lt;param name="collection"&gt;Pass collection of objects&lt;/param&gt;
    public CsvConverter(IEnumerable&lt;T&gt; collection)
    {
        foreach (var item in collection)
        {
            this.Add(item);
        }
    }

    /// &lt;summary&gt;
    /// Create new Instance of T object
    /// &lt;/summary&gt;
    /// &lt;returns&gt;&lt;/returns&gt;
    protected T GetObject()
    {
        return (T)Activator.CreateInstance(typeof(T),true);
    }

    /// &lt;summary&gt;
    /// Build object from CSV string to collection
    /// &lt;/summary&gt;
    private void BuildObject()
    {
        if (!string.IsNullOrEmpty(_csvText))
        {
            //Get first line from CSV string, than split by comma to get column names
            var _csvLines = _csvText.Split(_separetor);
            var _columnName =_csvLines[0].Split(',');


            for (int i = 1; i &lt; _csvLines.Length; i++)
            {
                var line = _csvLines[i].Split(',');

                T obj = GetObject();
                Type t = obj.GetType();
                PropertyInfo[] props = t.GetProperties();

                int colIndx = 0;
                foreach (string str in line)
                {
                    PropertyInfo find = props.First(x =&gt; x.Name == _columnName[colIndx]);
                    find.SetValue(obj, Convert.ChangeType(str,find.PropertyType),null);

                    //propertyInfo.SetValue(propertyInfo.PropertyType, line[0]);
                    colIndx++;
                }
                this.Add(obj);
            }
        }
        else
        {
            throw new System.NullReferenceException("No CSV string has passed in the parameter");
        }
    }

    /// &lt;summary&gt;
    /// Returns CSV string from collection of T object
    /// &lt;/summary&gt;
    /// &lt;returns&gt;string&lt;/returns&gt;
    public string GetCsvString()
    {
        StringBuilder sb = new StringBuilder();
        foreach (var item in this)
        {
            Type t = item.GetType();
            PropertyInfo[] props = t.GetProperties();
            string ln = "";
            foreach (PropertyInfo prp in props)
            {
                ln= ln+($"{prp.GetValue(item)},");
            }
            sb.AppendLine($"{ln.TrimEnd(',')}");
        }
        return sb.ToString();
    }
}


get collection of object from csv string

        var csv = await System.IO.File.ReadAllTextAsync("test.csv");
        List&lt;TestC&gt; csvBarcode = new CsvConverter&lt;TestC&gt;(csv.TrimEnd());


get csv string from collection of object

        CsvConverter&lt;TestC&gt; b = new CsvConverter&lt;TestC&gt;(list);
        return Content(b.GetCsvString());
I would suggest using the new() generic type constraint. Using Activator means you can match a private constructor which you would no longer be the case with the generic constraint but you would be able to catch incorrect use at compile time. Currently, if I tried to use a class like:

 public class Foo
 {
     public Foo(string bar, double baz) { /* ... */ }
 }


Your class would throw at runtime (a MethodMissingException I believe). If you added where T : class, new() instead of just where T : class, trying to use your class with the Foo type would produce a compile time error. An error I can fix before having to run the code is the most helpful kind.



Doing reflection in a loop when you don't need to is not a good thing. You do this for every line in the input file:

 T obj = GetObject();
 Type t = obj.GetType();
 PropertyInfo[] props = t.GetProperties();


You can create this all before processing the file and you don't need to create an instance to get the type information:

PropertyInfo[] props = typeof(T).GetProperties();

for (int i = 1; i &lt; _csvLines.Length; i++)
{
    T obj = GetObject(); // or T obj = new T(); with the constraint added.




You probably want the PropertyInfo[] to be an IDictionary&lt;string, PropertyInfo&gt;. to simplify the lookup by column name.



As for whether this should be a class or not... If you do the reflection in the constructor and keep the instance around to process multiple files then I think it is okay to be a class to save on having to do the reflection over and over again. 

If you are going to create an instance to process a file and then throw it away, or if you don't move the reflection to the constructor, I think it would be better as a static class with 2 methods as the other review suggests.



It's spelt: "separator" not "separetor". You've used both spellings. It's a word that I almost always spell wrong too :)