2012-08-24 37 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錯誤,我在我的問題中顯示編輯 –

相關問題