2012-02-21 37 views
31

Tôi có mã số Func<TCollection, T> trong mã của mình. Tôi sử dụng nó để chọn các thuộc tính nhất định.Tạo biểu thức từ Func

Trong cuộc gọi đến phương thức khác, tôi cần Expression<Func<TCollection, T>> làm tham số.

Có cách nào để chuyển đổi (hoặc tạo từ) Func<TCollection, T> đến Expression<Func<TCollection, T>> không?

Cảm ơn

Trả lời

30

Bạn không thể tạo lại biểu thức dựa trên phương thức vì biểu thức cần biết các câu lệnh gốc chứ không phải IL. Tuy nhiên bạn có thể tạo một Expresson mà làm cho một cuộc gọi phương pháp để func của bạn như: Tuy nhiên

Func<int> func =() => 1; 
Expression<Func<int>> expression = Expression.Lambda<Func<int>>(Expression.Call(func.Method)); 

Lưu ý rằng các hệ thống như EF có thể không thực sự làm việc với điều này

+2

Giả sử bạn * có thể * nhận được IL, tuy nhiên, bạn có thể dịch ngược IL, như Reflector và ILSpy. (Tất nhiên, không có gì đảm bảo rằng điều này sẽ chính xác giống như mã mà từ đó IL được biên soạn.) Có cách nào để lấy IL của một đại biểu không? – phoog

+5

Tôi nghĩ bạn có thể cần thêm mục tiêu func.Trong cuộc gọi của mình. Tôi đã thử điều này với một Func phức tạp hơn <> và nó phàn nàn tôi đã cố gắng gọi một phương pháp dụ với một đối tượng null. Tôi đã đổi nó thành Expression.Call (Expression.Constant (func.Target), func.Method, args) và tất cả đều tốt – ben

25

Trong khi bạn có thể chỉ cần tạo một cây biểu mà gọi cho đại biểu của bạn, nó sẽ không hữu ích - bởi vì đại biểu về cơ bản sẽ là một hộp đen xa như mã phân tích cây biểu hiện có liên quan. Giả sử bạn đang cố gắng sử dụng một cái gì đó như LINQ to SQL, trình phân tích truy vấn sẽ cần phải có khả năng quan sát logic của bạn để chuyển đổi nó thành SQL - và nó không thể làm điều đó nếu nó đạt đến một đại biểu đơn giản.

Bạn có lẽ nên thay đổi mã đi kèm với đại biểu ở nơi đầu tiên, để tạo cây biểu thức thay thế.

7

Bạn có thể làm một cái gì đó như thế này:

Func<object, string> func = a => a.ToString(); 
Expression<Func<object, string>> expr = a => func(a); 

Nhưng bạn sẽ chỉ nhận được một biểu thức có chứa lời gọi phương thức của mình vào Func gốc. Bạn sẽ không thể phân tích nội dung của chính func.

+4

Nhưng tự nhiên ông Skeet đặt nó tốt hơn tôi nhiều! :-) – Simon

9

Bạn không thể tạo biểu thức từ đại biểu (từ Func<TCollection, T> đến Expression<Func<TCollection, T>>) nhưng bạn có thể thực hiện việc làm mờ.

Tức là, chuyển đổi Expression<Func<TCollection, T>> thành Func<TCollection, T> bằng cách biên dịch nó (.compile). Vì vậy, nếu bạn cần cả hai, bạn có thể sử dụng các biểu thức tại các hàm của bạn và trong trường hợp bạn cần nó, biên dịch và thực hiện chúng trên một đối tượng bộ sưu tập được cung cấp.

Chúng tôi phải lưu ý tất nhiên việc biên dịch biểu thức chậm.

+0

Xin cảm ơn, đã cứu tôi, ( – Akbari

+0

Đây chính xác là những gì tôi cần. Chỉ cần cố gắng giảm mã trùng lặp. Có vẻ như tôi đã xem nó sai cách –

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