2010-09-08 24 views
21

tôi cần để có thể có được một cái gì đó tương tự như sau để làm việc:IQueryable OfType <T> trong đó T là một loại thời gian chạy

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

Đây có phải là có thể? Tôi có thể sử dụng .NET 4 nếu có gì mới cho phép điều này.

+3

Bạn muốn tự hỏi mình 'tại sao?' Một cách cẩn thận. – leppie

+0

Phải là IQueryable? Từ ví dụ của bạn, IEnumerable có vẻ đủ. –

+0

@leppie Tôi không hiểu điểm của bạn .. – Tablet

Trả lời

36

Bạn có thể gọi nó bằng cách phản ánh:

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

Một thay thế sẽ được để viết riêng OfTypeAndToArray phương pháp chung của bạn để làm cả hai bit của nó, nhưng ở trên nên làm việc.

+0

Skeet công trình này, một huyền thoại - Tôi sẽ sử dụng lược tả SQL để xem nó có đang lọc hay không sau khi truy xuất bộ sưu tập hoặc một phần của truy vấn .. trừ khi bạn biết câu trả lời cho điều đó nữa! – Tablet

+1

@Shahin: Nó phải làm điều đúng - nó gọi là 'Queryable.Where' thay vì' Enumerable.Where', sau khi tất cả. –

+0

@ Skeet bạn có biết tại sao nó có thể là bộ nhớ đệm từ tập kết quả đầu tiên mà nó nhận được không? – Tablet

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

Điều đó sẽ không trả lại toàn bộ nội dung của Tài nguyên trước khi chạy nơi chống lại nó? Sử dụng OfType trên bối cảnh này chạy nó trong SQL (tôi đang sử dụng Zentity) – Tablet

+0

Ngoài những gì Shahin nói, điều này cũng sai đối với các loại đa hình. – Timwi

+0

Nó nói tên không gian tên được mong đợi khi tôi thử và làm điều đó – Tablet

8

Hình như bạn sẽ cần phải sử dụng Reflection đây ...

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

Cảm ơn sự giúp đỡ của bạn! – Tablet

0

thuần túy về câu hỏi của bạn để sử dụng "Generics", Không nó không phải là có thể.

Generics là một tính năng thời gian biên dịch và không phải là khám phá thời gian chạy. Đối với thời gian chạy, bạn cần sử dụng Reflection hoặc Dynamic.

+2

Meh, tôi không thích đặc điểm của "generics là một tính năng thời gian biên dịch." Đó là điều đó và cũng có thể là một tính năng thời gian chạy (không giống Java). –

+0

Bạn có thể không thích nó, nhưng những gì quan trọng là generics là một tính năng thời gian biên dịch. Loại chung được biên dịch với kiến ​​thức về T. Nếu bạn có thể thể hiện bằng cách khác, hãy khai sáng cho tôi. – Aliostad

+0

Nếu nó không phải là một tính năng thời gian chạy thì MakeGenericType có thể hoạt động như thế nào? – Casey

0

gì về ...

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 })); 
    } 
Các vấn đề liên quan