2010-09-08 20 views
21

我需要能夠得到類似的東西以下工作:IQueryable的OfType <T>其中T是一個運行時類型

Type type = ??? // something decided at runtime with .GetType or typeof; 
object[] entityList = context.Resources.OfType<type>().ToList(); 

這可能嗎?我可以使用.NET 4,如果有什麼新的允許的話。

+3

你要問自己'爲什麼?'小心。 – leppie 2010-09-08 16:17:47

+0

它必須是IQueryable嗎?從你的例子來看,IEnumerable似乎就足夠了。 – 2010-09-08 16:18:37

+0

@leppie我不明白你的觀點。 – Tablet 2010-09-08 22:38:15

回答

36

您可以通過反射調用它:

MethodInfo method = typeof(Queryable).GetMethod("OfType"); 
MethodInfo generic = method.MakeGenericMethod(new Type[]{ type }); 
// Use .NET 4 covariance 
var result = (IEnumerable<object>) generic.Invoke 
     (null, new object[] { context.Resources }); 
object[] array = result.ToArray(); 

另一種方法是寫自己的OfTypeAndToArray泛型方法做它兩個位,但上面的應該工作。

+0

Skeet的工作原理,什麼傳說 - 我只是要使用SQL事件探查器來查看它是否在檢索集合之後進行篩選或作爲查詢的一部分。除非你也知道答案! – Tablet 2010-09-08 16:28:13

+1

@Shahin:它應該做正確的事情 - 畢竟,它叫做Queryable.Where而不是Enumerable.Where。 – 2010-09-08 16:29:52

+0

@Skeet你知道爲什麼它可能從它收到的第一個結果集中緩存嗎? – Tablet 2010-09-08 16:58:20

-1
object[] entityList = context.Resources 
           .Where(t=> t.GetType() == type) 
           .ToArray(); 
+0

在運行反對它之前,是不是會返回資源的全部內容?在這個上下文中使用OfType在SQL中運行它(我使用的是Zentity) – Tablet 2010-09-08 16:18:13

+0

除Shahin說的外,這對於多態類型也是錯誤的。 – Timwi 2010-09-08 16:19:55

+0

它說當我嘗試並做到這一點時期望名稱空間的名稱 – Tablet 2010-09-08 16:23:02

8

看起來你需要在這裏使用反射...

public static IEnumerable<object> DyamicOfType<T>(
     this IQueryable<T> input, Type type) 
{ 
    var ofType = typeof(Queryable).GetMethod("OfType", 
        BindingFlags.Static | BindingFlags.Public); 
    var ofTypeT = ofType.MakeGenericMethod(type); 
    return (IEnumerable<object>) ofTypeT.Invoke(null, new object[] { input }); 
} 

Type type = // ...; 
var entityList = context.Resources.DynamicOfType(type).ToList(); 
+0

感謝您的幫助! – Tablet 2010-09-08 22:36:41

0

單純就你的問題使用「仿製藥」,不,它是不可能的。

泛型是編譯時功能,而不是運行時發現。對於運行時,您需要使用反射或動態。

+2

呃,我不喜歡「泛型是編譯時特性」的表徵。它就是這樣,也是一個運行時功能(與Java不同)。 – 2010-09-08 16:35:06

+0

你可能不喜歡它,但重要的是泛型是編譯時的一個特性。通用類型是與T的知識編譯的。如果您可以另外顯示,請賜教。 – Aliostad 2010-09-08 17:39:04

+0

如果它不是運行時功能,MakeGenericType如何工作? – Casey 2014-09-19 17:53:46

0

怎麼樣......

public static IList OfTypeToList(this IEnumerable source, Type type) 
    { 
     if (type == null) 
      throw new ArgumentNullException(nameof(type)); 
     return 
      (IList) Activator.CreateInstance(
       typeof(List<>) 
        .MakeGenericType(type), 
       typeof(System.Linq.Enumerable) 
        .GetMethod(nameof(System.Linq.Enumerable.OfType), 
           BindingFlags.Static | BindingFlags.Public) 
        .MakeGenericMethod(type) 
        .Invoke(null, new object[] { source })); 
    } 
相關問題