0

I'm creating a datareader from a SqlCommand and I currently store this information in a class with the following

    private object PopulateObjectWithFields(SqlDataReader read, Type className)
    {
        var gd = Activator.CreateInstance(className);
        for (int i = 0; i < read.FieldCount; i++)
        {
            var type = gd.GetType();

            var fi = type.GetField(read.GetName(i));
            if (fi != null)
            {
                if (!Convert.IsDBNull(read[i]))
                {
                    try
                    {
                        fi.SetValue(gd, read[i]);
                    }
                    catch
                    {
                        throw new Exception(string.Format("Unable to set {0}. Class type {1}. DB Type {2}", read.GetName(i), fi.FieldType.Name, read[i].GetType().Name));
                    }
                }
            }
            else
            {
                var pi = type.GetProperty(read.GetName(i));
                if (pi != null)
                {
                    if (!Convert.IsDBNull(read[i]))
                    {
                        try
                        {
                            pi.SetValue(gd, read[i]);
                        }
                        catch
                        {
                            throw new Exception(string.Format("Unable to set {0}. Class type {1}. DB Type {2}", read.GetName(i), fi.FieldType.Name, read[i].GetType().Name));
                        }
                    }
                }
            }
        }
        return gd;
    }

This works perfectly. What I would like now is to put it in a List<class>, but I can't seem to get it right to create a List<class> dynamically.

Can someone maybe help me out with the syntax?

var MyList = List<MyClass> //This should be dynamically created

using(var reader = cmd.ExecuteReader())
{
      while (reader.Read())
      {
           MyList.Add(PopulateObjectWithFields(read, MyClass));
      }
}

LET ME CLARIFY I don't know what columns is going to be in the reader, and I don't know what class is going to be passed in. I have a generic method that needs to populate ANY reader to ANY class as long as the column names match the property of fields in the class

Jaques
  • 2,215
  • 1
  • 18
  • 35
  • Can you make it a generic method instead of passing in the `Type` as a parameter? – Jon Skeet Apr 22 '15 at 09:45
  • I have one like that as well, I use `var gdtype = Assembly.GetExecutingAssembly().GetTypes().First(t => t.Name == className);` to get the type from a string, so it does not really matter – Jaques Apr 22 '15 at 09:47
  • 1
    http://stackoverflow.com/questions/1464883/how-can-i-easily-convert-datareader-to-listt – Sreerejith S S Apr 22 '15 at 09:48
  • Guys, I need a generic way of creating the LIST. not mapping or converting anything. I want a dynamic way of creating the `List` – Jaques Apr 22 '15 at 09:52
  • 1
    Also note your solution can be improved in performance - you use reflection to get list of properties for every single row; you can prepare list of reflected properties upfront and reuse the mapping. – Ondrej Svejdar Apr 22 '15 at 09:52
  • For just creating instance of generic list - see http://stackoverflow.com/questions/11509695/generic-list-by-using-reflection – Ondrej Svejdar Apr 22 '15 at 09:55
  • Better to use an existing ORM than trying to create your own. – Magnus Apr 22 '15 at 09:58

1 Answers1

2

You should use generics:

private T PopulateObjectWithFields<T>(SqlDataReader read) where T : new()

The implementation of your method stays the same, except that you use T instead of MyClass, and that you can instantiate the type directly using the constructor:

var gd = new T();

From there, you can easily store your objects in your list:

var MyList = List<MyClass> //This should be dynamically created

using(var reader = cmd.ExecuteReader())
{
      while (reader.Read())
      {
           MyList.Add(PopulateObjectWithFields<MyClass>(read);
      }
}
Kevin Gosse
  • 38,392
  • 3
  • 78
  • 94
  • Ok, although it is a good answer, that is not what I'm looking for. I want to create the the `List` dynamically, so I want to get a List without specifying the type. The `PopulateObjectWithFields`, although not as neat as yours, is currently working fine – Jaques Apr 22 '15 at 09:50
  • @Jaques Why do you need that? Generics is the way to go. – Magnus Apr 22 '15 at 09:52
  • @Jaques Oh I think I understand now. How do you get "MyClass" in first place, from a string? If so, then indeed generics don't solve your issue. But then, do you need a strongly typed list, since you don't have static typing information in first place? It's hard to tell with the bit of code your shown, but maybe a `List` is enough for your use case – Kevin Gosse Apr 22 '15 at 09:54
  • I use `var gdtype = Assembly.GetExecutingAssembly().GetTypes().First(t => t.Name == className);` to get the class from a string. I've tried List but it gave me a lot of issues, specifically when I try to use the values in a combobox or something – Jaques Apr 22 '15 at 10:00