أحمد محروس
أحمد محروس

Reputation: 39

Instantiate an IQueryable<> from a refelected type

I have a ClassName string. I created a reflected List of objects:

Type objectType = Type.GetType(ClassName);
var listObjectType = typeof(List<>);
var constructedListObjectType = listObjectType.MakeGenericType(objectType);
object listObject = Activator.CreateInstance(constructedListObjectType);

Now I want listObject to be IQueryable<ClassName> not List<ClassName>.

Upvotes: 0

Views: 1389

Answers (3)

xanatos
xanatos

Reputation: 111870

Unclear what you want to do, but you asked for something and you'll get what you asked.

string className = "System.String";
Type type = Type.GetType(className);
var listType = typeof(List<>).MakeGenericType(type);

// This is a List<type> but it is easier to handle it through
// its non-generic IEnumerable interface
var list = (IEnumerable)Activator.CreateInstance(listType);

// Note that in truth this will return a IQueryable<type>
IQueryable queryable = Queryable.AsQueryable(list);

There are two overloads for Queryable.AsQueryable. One requires a IEnumerable<T> and returns the corresponding IQueryable<>, the other requires a IEnumerable, checks that in truth it is a IEnumerable<T> and returns a IQueryable<T> downcasted to IQueryable. I'm using the second one.

Upvotes: 2

Vladi Pavelka
Vladi Pavelka

Reputation: 926

Would this work for you?

    [Fact]
    public void Test()
    {
        var listGenericParameter = typeof(ClassName);
        var listObjectType = typeof(List<>);
        var constructedListObjectType = listObjectType.MakeGenericType(listGenericParameter);
        var listInstance = Activator.CreateInstance(constructedListObjectType);
        var asQueryableMethod = typeof(Queryable).GetMethod(nameof(Queryable.AsQueryable), new[] { typeof(IEnumerable) }) ??
                                throw new InvalidOperationException($"Could not find method AsQueryable() on type {nameof(Queryable)}");

        var listAsQueryable = asQueryableMethod.Invoke(null, new [] { listInstance });
        // method.Invoke('method owner instance', 'method args') 
        // first arg is null because AsQueryable() is extension method = static 
        // => there is no instance "owning" the method (just an owner type)

        (listAsQueryable is IQueryable<ClassName>).Should().BeTrue();
    }

    public class ClassName { }

edit: fixed the code to not be missleading, after comments from xonos

Upvotes: 0

Bob Vale
Bob Vale

Reputation: 18474

This helper method should do what you want. Inside of CreateList you can do what you like with the strongly typed list. GetQuerable will return the querable cast as an object.

Obviously make sure you have the correct usings so that AsQuerable() works

public static class Helper
{

    public static object GetQueryable(string type) {
        var method = typeof(Helper).GetMethod(nameof(CreateList));
        return method.MakeGenericMethod(Type.GetType(type)).Invoke(null, new object[0]);
    }

    public static IQueryable<T> CreateList<T>()
    {
        return new List<T>().AsQueryable();
    }
}

To Use:

var listObject  = Helper.GetQuerable("System.Int32");

Upvotes: 1

Related Questions