Search code examples
c#genericscasting

IEnumerable to array of T[]


Perhaps the question title is incorrect. I have the following variables

IEnumerable x = // some IEnumerable
System.Type y = // some type

How can iterate over x in order to generate an array with items of type y?

When I look into the internet I found:

public T[] PerformQuery<T>(IEnumerable q)
{                         
        T[] array = q.Cast<T>().ToArray();
        return array;
}

Note I cannot call that method PerformQuery becuase y is of type System.Type in other words calling it as PerformQuery<typeof(y)>(x); or PerformQuery<y>(x); will give me a compiler error.


edit

Here is the reason why I have that problem. I have web service where I post to it two things. The type of table I will like to query (example typeof(Customer)), and the actual string query example "Select * from customers"

    protected void Page_Load(object sender, EventArgs e)
    {
        // code to deserialize posted data
        Type table = // implement that here
        String query = // the query that was posted

        // note DB is of type DbContext
        IEnumerable q = Db.Database.SqlQuery(table, query );

        // here I will like to cast q to an array of items of type table!

Solution

  • You can use Expression Trees:

    public static class MyExtensions
    {
        public static Array ToArray(this IEnumerable source, Type type)
        {
            var param = Expression.Parameter(typeof(IEnumerable), "source");
            var cast = Expression.Call(typeof(Enumerable), "Cast", new[] { type }, param);
            var toArray = Expression.Call(typeof(Enumerable), "ToArray", new[] { type }, cast);
            var lambda = Expression.Lambda<Func<IEnumerable, Array>>(toArray, param).Compile();
    
            return lambda(source);
        }
    }
    

    It generates x => x.Cast<Type>().ToArray() for you, with Type known at runtime.

    Usage:

    IEnumerable input = Enumerable.Repeat("test", 10);
    Type type = typeof(string);
    
    Array result = input.ToArray(type);