TrentM
TrentM

Reputation: 136

How do I pass a class to a generic without hardcoding the class?

I'm using Bryan Tubbs' excellent code for populating a list generically. That all works great.

In his code he passes the employee class to his GenericPopulator method.

var employeeList = new Classes.GenericPopulator<employee>().CreateList(reader);

I am trying to come up with an even more dynamic solution. How would I pass the employee class generically? Or maybe it's dynamically? Or maybe I have to use reflection? It seems like there's a way to do this but I just can't quite get the syntax correct. I've tried passing the class, typeof(class), the type, an object of that type, and probably a few other guesses. I can't get any of them to work.

I have a fiddle here...

Line 44 works by passing MySchool. But what I really want is for line 51 to work. If I comment out 44 and uncomment 51 Visual Studio gives a cannot implicitly convert type error (in Fiddle it instead gives a type or namespace not found error). What do I need to do to line 51 to pass MyClass to GenericGetList<T> correctly? And obviously if 51 needs to be changed perhaps the GenericGetList method needs a tweak as well.

The ultimate goal, if you haven't figured it out, is to be able to pass any class to GenericGetList<T> and have it work for that class. So from GetListMySchool I could fill a list of IList<MySchool> while from GetListMyTeacher I could fill a list of IList<MyTeacher>. GetListXXX can have the class hard coded into it but GenericGetList needs to work with whatever class is passed to it. Is this possible?

Thanks!

EDIT

Editing line 32 to change it as Megatron suggested to

IList<MySchool> myList_Dynamic = new GenericGetList<MySchool>().GetList();

does certainly work for the code I originally posted. However the reason I'm calling GetList_Dynamic in line 34 is because in my unsimplified/unfiddled version of code my GetList function needs to be passed a SqlDataReader.

The GetList_Dynamic function gets the data reader and then calls GetList. So I've modified the Fiddle code to show GetList receiving a SqlDataReader parameter. That requires I change line 44 to pass the datareader and I added the datareader in line 42. Code to call the database, populate the reader, handle errors, etc would go between line 42 and 44.

So back to Megatron's idea of simply editing line 32...I don't have the datareader at that point to be able to pass it to the GetList method. Hence my desire to pass something on line 34 that could be used later once I've got my datareader all populated.

I have updated the Fiddle to include the SqlDataReader.

Upvotes: 0

Views: 234

Answers (1)

holly_cheng
holly_cheng

Reputation: 2471

This is a common misconception when learning to use generics. Generic types must be declared at compile time; they cannot be set at run time, because the whole point of using generics is to ensure type safety. The compiler is making sure that when <Employee> is the type parameter for GenericPopulator, then CreateList will return List<Employee>. In your fiddle, it has no idea how it's supposed to convert MySchool into MyClass. Thus, it's simply not possible to do what you're asking.

You probably need to read up on generics: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/generics/

Upvotes: 1

Related Questions