Solved

Dynamically Typed List

Posted on 2013-01-17
11
28 Views
Last Modified: 2016-07-02
Hi There

I'm trying to create a static function in c# .net that I can use to turn a line of MySQL in to a List<T> where T is of a generic type.

I find myself repeatedly creating the following code for each type that I use it for (in this case, the type Train)

        private static List<Train> GetTrainListFromSQL(string sql)
        {
            DataTable dt = DB.GetTable(sql);
            List<Train> TrainList = new List<Train>();
            foreach (DataRow dr in dt.Rows)
            {
                TrainList.Add(new Train(Convert.ToInt32(dr["id"])));
            }
            return TrainList;
        }

        public static List<Train> AllTrains()
        {
            return GetTrainListFromSQL("SELECT * FROM trains WHERE deleted = 0 ORDER BY tt_time DESC");
        }

Is there a way where I can call just one common static function where I can pass any of my objects (maybe with a common interface) so that I can simply convert a database to a list<t> without having to clone the code and just change the type reference each time? I.e I have exactly the same method in my WebPage object called:

private static List<WebPage> GetWebPageListFromSQL(string sql)
        {
            DataTable dt = DB.GetTable(sql);
            List<WebPage> WebPageList = new List<WebPage>();
            foreach (DataRow dr in dt.Rows)
            {
                WebPageList.Add(new WebPage(Convert.ToInt32(dr["id"])));
            }
            return WebPageList;
        }


Thanks in advance!
0
Comment
Question by:terryatnexus
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
11 Comments
 
LVL 44

Accepted Solution

by:
AndyAinscow earned 334 total points
ID: 38787869
I think the following is basically what you mean
        private static List<T> foo<T>()   //function that accepts generics, returns a list of generics
        {
            return new List<T>();
        }

//example of how to call the function
        private void x()
        {
            List<int> l = foo<int>(); 

Open in new window



You would need to add you SQL code, I did the above for brevity to show how it works
0
 

Author Comment

by:terryatnexus
ID: 38787943
That's really helpful thank you. I've got 95% the way there, I just have 1 problem with line that contains:

GenericList.Add(new typeof<T>(Convert.ToInt32(dr["id"])));


How do I create an instance of that type in order to add it to the list?

My New Code:

        private static List<T> GetListFromSQL<T>(string sql)   //function that accepts generics, returns a list of generics
        {
            DataTable dt = DB.GetTable(sql);
            List<T> GenericList = new List<T>();
            foreach (DataRow dr in dt.Rows)
            {
                GenericList.Add(new typeof<T>(Convert.ToInt32(dr["id"])));
            }

            return GenericList;
        }

        public static List<Train> AllTrains()
        {
            return GetListFromSQL<Train>("SELECT * FROM trains WHERE deleted = 0 ORDER BY tt_time DESC");
        }

Open in new window

0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 38788003
        private static List<T> foo<T>() where T : new()  //requires T supports new
        {
            List<T> l = new List<T>();
            l.Add(new T());
            return l;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            List<int> l = foo<int>();

Open in new window

0
How Do You Stack Up Against Your Peers?

With today’s modern enterprise so dependent on digital infrastructures, the impact of major incidents has increased dramatically. Grab the report now to gain insight into how your organization ranks against your peers and learn best-in-class strategies to resolve incidents.

 

Author Comment

by:terryatnexus
ID: 38788015
Almost there - I need to pass the int in to the new() constructor - I currently get:

'T': cannot provide arguments when creating an instance of a variable

How can I pass the int in to the constructor?
0
 
LVL 75

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 166 total points
ID: 38788415
Change:

GenericList.Add(new typeof<T>(Convert.ToInt32(dr["id"])));

to:

GenericList.Add(new T(Convert.ToInt32(dr["id"])));

Open in new window


You cannot use new and typeof in the manner you are attempting.
0
 
LVL 44

Assisted Solution

by:AndyAinscow
AndyAinscow earned 334 total points
ID: 38788809
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }


        public abstract class MyBaseClass
        {
            public abstract void SetVal(int i);
        }

        public class MyClass : MyBaseClass
        {
            public int somevar;

            public MyClass() {}
            public override void SetVal(int i) { somevar = i; }
        }


        private  List<T> foo<T>() where T : MyBaseClass, new()
        {
            List<T> l = new List<T>();
            T x = new T();
            x.SetVal(42);
            l.Add(x);
            return l;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            List<MyClass> l = foo<MyClass>(); 
            
        }
    }
}

Open in new window



This is actually a quite complex looking thing - unfortunately I don't know an easier way.  (C'tors with parameters aren't allowed in generic methods apparently).

I've created a base abstract class to define a method - which is used to fill the actual generic object.  The generic method uses a generic which is of this type (you could use an interface instead - it might be better to do so).  So construction is two step: new followed by filling the empty object.
0
 

Author Comment

by:terryatnexus
ID: 38792138
I've managed to come up with my own working solution:

I've changed type T to an Interface that sets out the requirments for the method.

    public static List<IWebCoreObject> GetListFromSQL<IWebCoreObject>(string sql) where IWebCoreObject : new()
    {
        DataTable dt = DB.GetTable(sql);
        List<IWebCoreObject> GenericList = new List<IWebCoreObject>();
        foreach (DataRow dr in dt.Rows)
        {
            Type classType = typeof(IWebCoreObject);
            ConstructorInfo classConstructor = classType.GetConstructor(new Type[] { Convert.ToInt32(dr["id"]).GetType() });
            IWebCoreObject classInstance = (IWebCoreObject)classConstructor.Invoke(new object[] { Convert.ToInt32(dr["id"]) });
            GenericList.Add(classInstance);
        }
        return GenericList;
    }

Open in new window

0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 41682841
0
 
LVL 44

Expert Comment

by:AndyAinscow
ID: 41682844
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

We all know that functional code is the leg that any good program stands on when it comes right down to it, however, if your program lacks a good user interface your product may not have the appeal needed to keep your customers happy. This issue can…
This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
If you’ve ever visited a web page and noticed a cool font that you really liked the look of, but couldn’t figure out which font it was so that you could use it for your own work, then this video is for you! In this Micro Tutorial, you'll learn yo…
This is my first video review of Microsoft Bookings, I will be doing a part two with a bit more information, but wanted to get this out to you folks.

688 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question