将IEnumerable <T>转换为IQueryable <T>,其中T未知

Dom*_*rno 5 c# generics reflection

我有一个BindingSourceDataSource(定义为对象)IEnumerable在运行时可以是任何类型的类(例如IList<Foo>)。我需要将其转换为,IQueryable<T>以便可以将其传递给通用扩展名:

IOrderedQueryable<TEntity> OrderUsingSortExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class
Run Code Online (Sandbox Code Playgroud)

到目前为止,我有这个:

string order = "Message ASC";
Type thetype = bsTotalBindingSource.DataSource.GetType().GetGenericArguments()[0];
IEnumerable<object> totalDataSource = ((IEnumerable<object>)(bsTotalBindingSource.DataSource));
//Blowing up on this next line with 'System.Linq.Queryable is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true.'
MethodInfo asQueryableMethod = typeof(Queryable).MakeGenericType(thetype).GetMethod("AsQueryable", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IQueryable<>) }, null); 
MethodInfo genericAsQueryableMethod = asQueryableMethod.MakeGenericMethod(thetype);
MethodInfo orderUsingSortExpressionMethod = GetType().GetMethod("OrderUsingSortExpression");
MethodInfo genericUsingSortExpressionMethod = orderUsingSortExpressionMethod.MakeGenericMethod(thetype);
bsTotalBindingSource.DataSource = genericUsingSortExpressionMethod.Invoke(this, new object[] { genericAsQueryableMethod.Invoke(totalDataSource, null), order });
Run Code Online (Sandbox Code Playgroud)

如您所见,这里的最终目标是能够从DataSource中获取某些东西,获取其RuntimeType,IEnumerable<T>其中where T可以是任意值,然后进行调用,AsQueryable<T>以便可以将其传递到接受的函数中IQueryable<T>

编辑在深入挖掘以找到我正在寻找的方法后,我对这个问题已经走得更远了。现在看起来像这样:

string order = "Message ASC";
Type thetype = bsTotalBindingSource.DataSource.GetType().GetGenericArguments()[0];
//Returns the AsQueryable<> method I am looking for
MethodInfo asQueryableMethod = typeof(Queryable).MakeGenericType(thetype).GetMethods()[1]; 
MethodInfo genericAsQueryableMethod = asQueryableMethod.MakeGenericMethod(thetype);
MethodInfo orderUsingSortExpressionMethod = typeof(SortExtension)GetType().GetMethods()[0];
MethodInfo genericUsingSortExpressionMethod = orderUsingSortExpressionMethod.MakeGenericMethod(thetype);
bsTotalBindingSource.DataSource = genericUsingSortExpressionMethod.Invoke(this, new object[] { genericAsQueryableMethod
//blows up here with 'Object of type 'System.RuntimeType' cannot be converted to type 'System.Collections.Generic.IEnumerable`1[LogRecordDTO]'.'
.Invoke(bsTotalBindingSource.DataSource, new object[] {thetype}), order });
Run Code Online (Sandbox Code Playgroud)

Pet*_*eGO 6

你说你想转换IEnumerable<T>IQueryable<T>T 的类型未知的地方。

private void Test<T>(IEnumerable<T> x)
{
    var queryableX = x.AsQueryable();
}
Run Code Online (Sandbox Code Playgroud)

注意:您必须是using System.Linq.


Pet*_*eGO 1

我认为最简单的方法是重载(或添加扩展方法)到您想要调用的方法,以 IEnumerable 作为参数。然后只需从中调用另一个方法即可。这是我的意思的一个例子。

public class MyTestClass
{
    public void Run()
    {
        List<string> myList = new List<string>() { "one", "two" };

        object myListObject = (object)myList;

        Test(myListObject);
    }

    private void Test(object myListObject)
    {
        Type myGenericType = myListObject.GetType().GetGenericArguments().First();

        MethodInfo methodToCall = typeof(MyTestClass).GetMethods().Single(
            method => method.Name.Equals("GenericMethod") && method.GetParameters().First().Name.Equals("myEnumerableArgument"));

        MethodInfo genericMethod = methodToCall.MakeGenericMethod(myGenericType);

        genericMethod.Invoke(this, new object[] { myListObject });
    }

    public void GenericMethod<T>(IQueryable<T> myQueryableArgument)
    {
    }

    public void GenericMethod<T>(IEnumerable<T> myEnumerableArgument)
    {
        GenericMethod<T>(myEnumerableArgument.AsQueryable());
    }
}
Run Code Online (Sandbox Code Playgroud)