Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Dynamically Typed List

Posted on 2013-01-17
11
Medium Priority
?
42 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 45

Accepted Solution

by:
AndyAinscow earned 1336 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 45

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
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

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 664 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 45

Assisted Solution

by:AndyAinscow
AndyAinscow earned 1336 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 45

Expert Comment

by:AndyAinscow
ID: 41682841
0
 
LVL 45

Expert Comment

by:AndyAinscow
ID: 41682844
0

Featured Post

Visualize your virtual and backup environments

Create well-organized and polished visualizations of your virtual and backup environments when planning VMware vSphere, Microsoft Hyper-V or Veeam deployments. It helps you to gain better visibility and valuable business insights.

Question has a verified solution.

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

Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
This article shows how to deploy dynamic backgrounds to computers depending on the aspect ratio of display
In response to a need for security and privacy, and to continue fostering an environment members can turn to for support, solutions, and education, Experts Exchange has created anonymous question capabilities. This new feature is available to our Pr…
Please read the paragraph below before following the instructions in the video — there are important caveats in the paragraph that I did not mention in the video. If your PaperPort 12 or PaperPort 14 is failing to start, or crashing, or hanging, …

636 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