2012-04-23 39 views
7

Tôi có IQueryable < T> nguồn và tôi muốn tự động gọi IQueryable < T> .Count().Nhận Phương thức đếm() Phương pháp mở rộng LINQ trên tùy ý IQueryable <T>

Vì vậy, tôi cần MethodInfo of Count được khai báo trong IQueryable.

đây là chữ ký của mình (trong IQueryable <>) từ MSDN:

public static int Count<TSource>(
    this IQueryable<TSource> source 
) 

Đây là cách xa tôi đã nhận:

Expression expr; //this is expression which holds my IQueryable<T> 
MethodInfo mi = expr.Type.GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null); 

nhưng mi của tôi luôn luôn là null;

Tôi cũng đã cố gắng:

mi = typeof(IQueryable<>).GetMethod("Count", BindingFlags.Static | BindingFlags.Public, null, new[] { expr.Type }, null); 

nhưng một lần nữa null.

mục tiêu cuối cùng của tôi sẽ là:

Expression.Call(mi, expr); 

UPDATE: đây là làm thế nào tôi có được phương pháp Sum Extension:

MethodInfo sum = typeof(Queryable).GetMethod("Sum", BindingFlags.Static | BindingFlags.Public, null, new[] { typeof(IQueryable<decimal>) }, null); 

và các công trình này, nhưng phương pháp Sum này không chung chung. Đó là mặc dù tĩnh.

Trả lời

8

Bạn cần phải loại bỏ đối số chung của loại IQueryable<T> và sử dụng điều đó; cũng là loại sở hữu phương thức không phải là IQueryable<T>, nó là Queryable - nếu bạn nghĩ về nó - các giao diện không thể có các phương thức tĩnh (tốt, như một người bình luận đã chỉ ra, trong C# nghĩa là :)).

Ngoài ra, vì đó là một phương pháp chung bạn không thể phù hợp với các thông số theo cách bạn đã thử: bởi vì bạn cần phải vượt qua kiểu generic nétIQuerable<TSource> - không một generic loạiIQueryable<int> hoặc bất cứ điều gì biểu thức thực tế là.

Thay vào đó bạn chỉ có thể tìm kiếm một phiên bản đơn parametered của một phương pháp tĩnh gọi là 'Đếm' trên Queryable loại:

Type genericArgument = expr.GetGenericArguments()[0]; 

MethodInfo countMethod = typeof(Queryable) 
       .GetMethods(BindingFlags.Static | BindingFlags.Public) 
       //narrow the search before doing 'Single()' 
       .Single(mi => mi.Name == "Count" 
         // this check technically not required, but more future proof 
         && mi.IsGenericMethodDefinition 
         && mi.GetParameters().Length == 1) 
       .MakeGenericMethod(genericArgument); 

//now you can bind to 'countMethod' 

Cập nhật 07 tháng ba năm 2017 - Rõ ràng, một cái gì đó thay đổi trong khuôn khổ đã dừng phiên bản gốc của ví dụ mã hoạt động - đây là phiên bản cập nhật sẽ hoạt động

Đi sâu hơn một chút - chữ ký của phương thức là:

public static int Count<TSource>(
    this IQueryable<TSource> source 
) 

Vì vậy, trong khi các loại tham số là IQueryable<TSource> nó chung chung so với loại TSource - do đó lý do tại sao bạn cần phải cá vào biểu IQueryable<TSource> của bạn và lấy đó là chung cuộc tranh cãi. Và bạn cũng có thể thấy ý tôi về thông số ở đây.

+0

Ok, cảm ơn. Tôi sẽ thử nó. –

+0

Tôi đã thử nó nhưng nó vẫn là null: Loại type = expr.Type.GetGenericArguments() [0]; MethodInfo mi = typeof (Truy vấn) .GetMethod ("Đếm", BindingFlags.Static | BindingFlags.Public, null, new [] {type}, null); Nhưng, nếu tôi hiểu chính xác, hàm cuối cùng này sẽ trả về một thứ gì đó mà tôi cung cấp làm đối số thứ 4, đúng không? –

+0

@MilosMijatovic câu trả lời ban đầu của tôi không * khá * đúng đã cập nhật –

2

Để trình biên dịch lấy phương thức cho bạn.

Type genericArgument = expr.GetGenericArguments()[0]; 
var fakeExp = (Expression<Func<IQueryable<int>, int>>)(q => q.Count()); 
var mi = ((MethodCallExpression)fakeExp.Body).Method.GetGenericMethodDefinition().MakeGenericMethod(genericArgument); 
+0

Khi tôi thử Expression countEx = Expression.Call (propEx, mi); nó mang lại cho tôi lỗi: Phương thức tĩnh yêu cầu cá thể rỗng, phương thức không tĩnh yêu cầu cá thể không rỗng. Tên thông số: ví dụ – Roman

+1

Sử dụng quá tải lấy MethodInfo làm thông số đầu tiên (https://msdn.microsoft.com/en-us/library/dd323922%28v=vs.110%29.aspx) Đếm là một phương pháp mở rộng tĩnh trong lớp System.Linq.Queryable;) – MBoros

+0

Cheeeeeers !! Bây giờ nó hoạt động! Cảm ơn bạn! Tôi thích điều này như một câu trả lời, bởi vì điều này rõ ràng hơn với tôi. – Roman

Các vấn đề liên quan