Toby Fieldgroove
Toby Fieldgroove

Reputation: 625

How to create list of unknown/generic type in C#?

I noticed that I sort of do the same stuff over and over again and wanted to create a more generic method for converting the rows from a datatable to a specific class.

Since I have no experiance in using generic types I find it hard to know how to search for what I want but I'll try to explain.

I have created this class:

public class Class1
{
    public Guid? Id{ get; set; }
    public string Text1{ get; set; }
    public string Text2{ get; set; }
    public int TheNumber{ get; set; }
}

Then I fetch data from a database which represents the Class1. I get back the result in the form of a DataTable. The names in the columns of the datarows are exactly the same as in my class so I though I could use them somehow in my generic method to create instances of Class1.

At this point in time I create the instance like this:

public static Class1 AssembleClass1(DataTable dtInfo)
    {
        Class1 obj = null;

        if (dtInfo != null)
        {
            DataRow dr = dtInfo.Rows[0];
            obj = new StrategicObjectives();
            obj.Id= (Guid)dr["Id"];
            obj.Text1 = dr["Id"].ToString();
            obj.Text2 = dr["Id"].ToString();
            obj.TheNumber = (int)dr["TheNumber"];
        }

        return obj;
    }

Now, what I want to do is to create a generic method that takes the dataTable and the type of Class1 (since I have many other classes in my project I want to be able to do the same). It should then create a list of the type of Class1 and iterate the parameters of Class1, find the corresponding datacolumn in the row(s) of the datatable and assign the correct datarow value to the correct parameter of Class1. I guess it also needs to check the type of each parameter of Class1 to convert the datarow column type correctly.

I only got this far myself but I don't know if it's correct and I don't know how to continue.. :

public static List<T> AssembleItem<T>(DataTable dtItems)
    {
        List<T> items = null;

        if (dtItems != null)
        {
            items = new List<T>();

            foreach (DataRow dr in dtItems.Rows)
            {
                object item = (T)Activator.CreateInstance(typeof(T));
            }
        }

        return items;
    }

I hope someone can help me with this, please ask me if you need more information.

Upvotes: 3

Views: 951

Answers (2)

Tim Rutter
Tim Rutter

Reputation: 4679

You could use reflection to get the property names of the class and populate them.

public static List<T> AssembleItem<T>(DataTable dtItems) where T : new()
{
    List<T> items = null;
    if (dtItems != null)
    {
        items = new List<T>();
        foreach (DataRow dr in dtItems.Rows)
        {
            T item = new T();
            foreach (DataRow dr in dtItems.Rows)
            {
                T item = new T();

                Type t = typeof (T);
                foreach (var property in t.GetProperties(BindingFlags.Public))
                {
                    var propertyname = property.Name;

                    //var data = ...get data from row in database with same column name as   propertyname

                    property.SetValue(item,data);
                }
                // populate item from dr
                items.Add(item);
            }
        }
        return items;
    }
}

Upvotes: 1

Codor
Codor

Reputation: 17605

To answer the question in part, it is not necessary to use reflection to instatiate a type; you can use type constraints to require a parameterless constructor as follows.

public static List<T> AssembleItem<T>(DataTable dtItems) where T : new()
{
    List<T> items = null;
    if (dtItems != null)
    {
        items = new List<T>();
        foreach (DataRow dr in dtItems.Rows)
        {
            T item = new T();
            // populate item from dr
            items.Add(item);
        }
    }
    return items;
}

Upvotes: 2

Related Questions