2012-08-24 36 views
2

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

IOrderedQueryable<TEntity> OrderUsingSortExpression<TEntity>(this IQueryable<TEntity> source, string sortExpression) where TEntity : class 

到目前为止,我有这样的:

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 }); 

正如你所看到的,最终目标在这里为了能够从DataSource中获取某些东西,请获取其运行时类型IEnumerable<T>,其中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 }); 
+0

的问题是,我不知道什么是TElement,这就是为什么我试图通过反射 –

+0

我想你想失去'MakeGenericType'援引AsQueryable已,为'Queryable'的确是一个不一般类型。 – Rawling

+0

你可以发布你的方法和类,因为它们是我可以建立一个测试应用程序。 –

回答

0

我认为最简单的方法是将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()); 
    } 
} 
+0

我做了这个,它完美的作品。非常感谢。 –

1

不知道我是否理解这个问题 - 虽然我已经读了几次。你说你想将IEnumerable<T>转换成IQueryable<T>,其中T的类型是未知的。

private void Test<T>(IEnumerable<T> x) 
{ 
    var queryableX = x.AsQueryable(); 
} 

注意:您需要成为using System.Linq

+0

如果我不知道T是什么,我会怎么称呼它? –

+0

这就是泛型参数T的全部观点 - 你不需要知道调用这个方法是什么。或者你是否说你不知道整个IEnumerable 是什么?也就是说,你只有一个物体 - 但这个物体实际上可能是,比如说IList ?如果是这样,请删除您的downvote并修改您的问题,因为这不是您所说的。 – PeteGO

+0

BindingSource。DataSource是一个对象,因此理论上可以是任何东西。我已经更新了这个问题。为了记录,我从来没有低估过你,别人必须拥有,但似乎他们已经将其删除。 –

0

我认为有以下可能的工作:

// Get generic type argument for everything 
Type theType = bsTotalBindingSource.DataSource 
    .GetType().GetGenericArguments()[0]; 

// Convert your IEnumerable<?>-in-an-object to IQueryable<?>-in-an-object 
var asQueryable = 
    // Get IEnumerable<?> type 
    typeof(IEnumerable<>) 
    .MakeGenericType(new[] { theType }) 
    // Get IEnumerable<?>.AsQueryable<?> method 
    .GetMethod(
     "AsQueryable", 
     new Type[] { theType }, 
     System.Reflection.BindingFlags.Static | 
     System.Reflection.BindingFlags.Public) 
    // Call on the input object 
    .Invoke(bsTotalBindingSource.DataSource, new object[0]); 

// Sort this queryable 
var asSortedQueryable = 
    // Get the YourType<?> generic class your sorting generic method is in? 
    // If your class isn't generic I guess you can skip the MakeGenericType. 
    typeof(yourtype) 
    .MakeGenericType(new[] { theType }) 
    // Get the OrderUsingSortExpression<?> method 
    .GetMethod(
     "OrderUsingSortExpression", 
     new Type[] { theType }, 
     System.Reflection.BindingFlags.Static | 
     System.Reflection.BindingFlags.Public) 
    // Call on the IQueryable<?> object 
    .Invoke(dataSource, new object[] { order }); 

// Set this object to the data source 
bsTotalBindingSource.DataSource = asSortedQueryable; 

作为一个声明,我不是大规模明确这一点。例如当从IEnumerable<T>获得AsQueryable<T>时,是否需要传递泛型参数?但我相信你想做的事情是可能的,而确实需要反思,而我认为这是大致正确的。

+0

一旦使用该 “变种AsQueryable已= //获取的IEnumerable 类型的typeof(IEnumerable的<>) .MakeGenericType(新[] {theType}) //获取的IEnumerable .AsQueryable 方法 .GetMethod( “ AsQueryable已”, 新类型[] {theType}, System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public) //调用输入对象上 .Invoke(bsTotalBindingSource.DataSource,新的对象[] {方式});'它给我的System.RuntimeType错误,我在我的问题中显示编辑 –

相关问题