C# List of runtime Type (petapoco)

374 Views Asked by At

Trying to customize my petapoco experience, I have following situation:

class Animal
{
// common properties
}

class Dog:Animal
{
//particular properties including custom attributes for properly working with DB
}

class Cat:Animal
{
}

Normally, I use

List<Dog> ret = db.Query<Dog>("select * from dogs").ToList();

I created a list (Category) which keep tracks between tables in database and objects actually implemented in my code (eg. class dog)

So I obtain the type at runtime from Category list:

Type t = ((Category)Categories.Current).ObjectType;

In my debugger I can see the Dog type for t. But I don't know how to convert the runtime obtained type into something usable for

List<t> ret = db.Query<t>("select * from ...").ToList();

Thanks in advance,

PS. I don't want to use base Animal for query List since the result list will populate a GridView and derived classes (eg. Dog) contains specific attributes for displaying, filter, etc.

2

There are 2 best solutions below

0
On

I think the best you can do is to have something like this:

public static IList FetchAllByCategory(Type category)
{
    string sql = "select * from " + category.Name + "s";
    if (category == typeof(Dog)) return db.Fetch<Dog>(sql);
    if (category == typeof(Cat)) return db.Fetch<Cat>(sql);
    ...
}

Note that you cannot use List<Animal> as return type, as a list of a derived type is not assignment compatible to a list of a base type. IList is the greatest common denominator here. But there is a chance that the GridView actually sees the real List<T> assigned to its data source. (Usually data binding sources are typed as object anyway.

Fetch<T>() is like Query<T> but returns a List<T> instead of a IEnumerable<T>.

0
On

@Gábor Bakos thanks.

Well, I found a way but required to add a dummy virtual GetObjects() in Animal class, then override GetObjects() for each Dog, Cat and so on.

Type type = ((Category)Categories.Current).ObjectType; // get type
object rtObject = Activator.CreateInstance(type); // create instance
((Animal)rtObject).GetObjects(); // call some known base method

But this rise the question: do I need this complicated way?

I think I can just make a GetObjects() with hard coded switch by type, then call the real methods.