Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting Results from Generic Method Invocation?

Tags:

c#

.net

generics

I'm currently messing about with generics and I'm trying to write a function that I can call to load everything from a database table simply by specifying the table name.

I'm most of the way there; my generic methods all seem to work, but I'm not quite sure how to cast my results into something usable.

This is the guts of the method so far:

private static List<EntityCodeBase> GetCodeLoadResults(CodeTables table)
{
    List<EntityCodeBase> results = new List<EntityCodeBase>();
    Assembly assm = Assembly.Load(new System.Reflection.AssemblyName("RR"));
    Type tableType = assm.GetTypes().Where(u => u.Name.ToLower() == table.ToString().ToLower()).FirstOrDefault();
    MethodInfo mi = typeof(SpecificEntity).GetMethod("LoadAll");

    mi = mi.MakeGenericMethod(tableType);
    mi.Invoke(null, null); //how can I cast the resulting object into a List<EntityCodeBase> ?

    return results;
}
like image 839
Sonny Boy Avatar asked Feb 06 '13 21:02

Sonny Boy


1 Answers

Assuming SpecificEntity.LoadAll returns a list of some type derived from EntityCodeBase, you can't cast directly to a List<EntityCodeBase> but you can cast to IEnumerable<EntityCodeBase>. Then you can create a new list:

var ecbList = (IEnumerable<EntityCodeBase>)mi.Invoke(null, null);
return list.ToList();

It might be cleaner however, if you can get the table name from the entity type, either directly by name, using attributes, or using a map. Then you can make GetCodeLoadResults generic in the result type e.g.

private static List<T> GetCodeLoadResults() where T : EntityCodeBase
{
    Assembly assm = Assembly.Load(new System.Reflection.AssemblyName("RR"));
    Type tableType = //get table type from T
    MethodInfo mi = typeof(SpecificEntity).GetMethod("LoadAll");

    mi = mi.MakeGenericMethod(tableType);
    return (List<T>)mi.Invoke(null, null);
}

If you're not using .Net 4, you can't cast a List<TDerived> to an IEnumerable<TBase>, so you'll have to cast to IEnumerable first:

return ((System.Collections.IEnumerable)mi.Invoke(null, null))
    .Cast<EntityCodeBase>()
    .ToList();
like image 121
Lee Avatar answered Nov 02 '22 10:11

Lee