Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Linq Cast<T> with System.Type

Tags:

casting

linq

LinQ contains the method Cast which casts each entry in the list to type T. Lets say we have a list which looks like the following:

List<Object> obj = new List<Object>();
obj.Add("A");
obj.Add("B");

A working cast could be

var list = obj.Cast<string>();

What I would like to work

Type t = typeof(String);
Object list = obj.Cast(t);

A solution would be to use reflection and genericly create a list and populate it but I was wondering if there exist any better solution? Heard that .NET 4.0 should support some co/contra-variance which may be a way to do it.


Extra Information and Reflection Soulution

The error I get is the following The model item passed into the dictionary is of type System.Collections.Generic.List1[IStatisticEntry], but this dictionary requires a model item of type System.Collections.Generic.List1[CrashStatistic+CrashEntry]. Note that CrashEntry implements IStaticEntry but cannot be casted because it is a generic type of the list.

I constructed the following solution through I would stille like something without Reflection:

    public static object Cast(this IEnumerable list, Type type)
    {
        var newList = Activator.CreateInstance(typeof(List<>).MakeGenericType(type));

        foreach (var item in list)
            newList.GetType().GetMethod("Add").Invoke(newList, new object[] { item });

        return newList;
    }
like image 325
Søren L. Avatar asked Aug 10 '10 13:08

Søren L.


1 Answers

I don't quite understand why you'd want to do this but you could invoke Enumerable.Cast<T> through reflection:

List<object> objectList = new List<object> { "Foo", "Bar" };
object stringSequence = typeof(Enumerable)
    .GetMethod("Cast", BindingFlags.Public | BindingFlags.Static)
    .MakeGenericMethod(typeof(string))
    .Invoke(null, new[] { objectList });

In which case the runtime type of stringSequence would implement IEnumerable<string>.

like image 148
Trillian Avatar answered Oct 03 '22 01:10

Trillian