2010-05-17 25 views
9

Bạn có thể sử dụng Lambda Expression Objects để biểu thị lambda làm biểu thức.Gọi phương thức chung bằng cách sử dụng biểu thức lambda (và loại chỉ được biết khi chạy)

Làm thế nào để bạn tạo ra một Lambda Expression Object đại diện cho một cuộc gọi phương thức chung, nếu bạn chỉ biết loại-bạn sử dụng cho chữ ký phương pháp chung - lúc chạy?

Ví dụ:

Tôi muốn tạo ra một Lambda Expression Objects gọi: public static TSource Last<TSource>(this IEnumerable<TSource> source)

Nhưng tôi chỉ biết TSource là gì khi chạy.

+0

Điều này không hoàn toàn rõ ràng. Bạn đang cố gắng tạo phương pháp nào trên đối tượng nào? Bạn có muốn tham chiếu đến phương thức Last generic với một biểu thức lambda không? – casperOne

+0

@CasperOne: Xin chào Casper! a) Tôi đang cố gắng tạo một thể hiện của ** TheObject **, tham chiếu đến ** TheMethod **. b) có, tôi muốn tham khảo phương pháp cuối cùng với một biểu thức lambda (đối tượng biểu thức lambda tôi có ý nghĩa). Cám ơn:) – SDReyes

Trả lời

20
static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<T>), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { typeof(T) }, source); 

    return Expression.Lambda<Func<IEnumerable<T>, T>>(call, source) 
} 

hoặc

static LambdaExpression CreateLambda(Type type) 
{ 
    var source = Expression.Parameter(
     typeof(IEnumerable<>).MakeGenericType(type), "source"); 

    var call = Expression.Call(
     typeof(Enumerable), "Last", new Type[] { type }, source); 

    return Expression.Lambda(call, source) 
} 
2

Tôi không hiểu đầy đủ các câu hỏi, nhưng mã mà DTB viết có thể được viết đơn giản như:

class MyUtils { 
    public static Expression<Func<IEnumerable<T>, T>> CreateLambda<T>() { 
    return source => source.Last(); 
    } 
} 

Các mã trong mẫu bằng cách DTB là khá nhiều điều tương tự như những gì trình biên dịch C# tự động tạo ra cho bạn từ biểu thức lambda này (được biên dịch thành cây biểu thức, vì kiểu trả về là Expression).

Nếu bạn biết loại thời gian chạy, bạn có thể sử dụng giải pháp bằng dtb hoặc bạn có thể gọi phương thức CreateLambda (ở trên) bằng cách sử dụng Phản chiếu, có thể chậm hơn, nhưng cho phép bạn viết mã trong lambda C tự nhiên #:

var createMeth = typeof(MyUtils).GetMethod("CreateLambda"); 
LambdaExpression l = createMeth.MakeGenericMethod(yourType).Invoke(); 

những điều tốt đẹp về phương pháp này là các mã trong CreateLambda có thể phức tạp hơn nhiều, đó sẽ là thực sự khó khăn để làm bằng cây biểu hiện một cách rõ ràng.

+0

Xin chào Tomas! Tôi cần phải cải thiện kỹ năng giao tiếp lập trình của mình, tôi biết, tôi biết hahahha (nhưng đừng lo lắng tôi đang làm việc với nó:). Tôi đã cập nhật câu hỏi để đại diện cho những gì tôi thực sự muốn nói. Đẹp refactor! +1 – SDReyes

+0

@SDReyes: "lúc chạy" là điểm quan trọng. Bạn vẫn có thể sử dụng cú pháp C# tốt đẹp cho điều này mặc dù (không xây dựng một cách rõ ràng các cây biểu thức). Xem câu trả lời cập nhật của tôi. –

+0

Xin chào Tomas !, Tôi đồng ý với bạn. cách tiếp cận này cho phép bạn thực hiện các lambdas phức tạp dễ dàng bên trong phương thức CreateLambda (chỉ với một sự cân bằng hiệu suất). Tôi sẽ sử dụng phương pháp dtb lần này, bởi vì chúng ta đã sử dụng rất nhiều biểu thức trong thành phần mà chúng ta đang làm việc, và tôi muốn giữ sự gắn kết giữa mã:). nhưng tôi sẽ rất vui khi triển khai của bạn trong các kịch bản tiếp theo! Làm tốt lắm Tomas! Trân trọng. SD – SDReyes

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