views:

116

answers:

4

I need to be able to get something similar to the following to work:

Type type = ??? // something decided at runtime with .GetType or typeof;
object[] entityList = context.Resources.OfType<type>().ToList();

Is this possible? I am able to use .NET 4 if anything new in that allows this.

A: 
 object[] entityList = context.Resources
                              .Where(t=> t.GetType() == type)
                              .ToArray();
James Curran
Will that not return the entire contents of Resources before running the where against it? Using OfType on this context runs it in the SQL (I'm using Zentity)
Shahin
In addition to what Shahin said, this is also wrong for polymorphic types.
Timwi
It says namespace name expected when I try and do that
Shahin
+2  A: 

You can call it by reflection:

MethodInfo method = typeof(Queryable).GetMethod("OfType");
MethodInfo generic = method.MakeGenericMethod(new Type[]{ type });
// Use .NET 4 covariance
var result = (IEnumerable<object>) generic.Invoke
      (null, new object[] { context.Resources });
object[] array = result.ToArray();

An alternative would be to write your own OfTypeAndToArray generic method to do both bits of it, but the above should work.

Jon Skeet
Skeet this works, what a legend - I'm just going to use SQL profiler to see if it's doing the filtering after retrieving the collection or as part of the query.. unless you know the answer to that also!
Shahin
@Shahin: It should be doing the right thing - it's calling `Queryable.Where` instead of `Enumerable.Where`, after all.
Jon Skeet
@Skeet do you have any idea why it may be caching from the first result set it received?
Shahin
@Shahin: Are you reusing the same context? If so, that's probably what's wrong.
Jon Skeet
Thanks for this solution, better than my approach which was with beginner understanding on covariance, this is much cleaner.
Shahin
+2  A: 

Looks like you’ll need to use Reflection here...

public static IEnumerable<object> DyamicOfType<T>(
        this IQueryable<T> input, Type type)
{
    var ofType = typeof(Queryable).GetMethod("OfType",
                     BindingFlags.Static | BindingFlags.Public);
    var ofTypeT = ofType.MakeGenericMethod(type);
    return (IEnumerable<object>) ofTypeT.Invoke(null, new object[] { input });
}

Type type = // ...;
var entityList = context.Resources.DynamicOfType(type).ToList();
Timwi
Thanks for your help!
Shahin
A: 

Purely on your question to use "Generics", No it is not possible.

Generics is a compile time feature, and not a runtime discovery. For runtime, you need to use Reflection or Dynamic.

Aliostad
Meh, I don't like the characterization of "generics is a compile time feature." It's that and also demonstrably a runtime feature (unlike Java).
Kirk Woll
You may not like it but what matters is that generics is a compile time feature. Generic type is compiled with the knowledge of the T. If you can show otherwise, please enlighten me.
Aliostad