2013-06-02 35 views
6

Tôi tìm thấy một đoạn mã có dạng như sau:Cú pháp để tham chiếu một phương thức trả về một biểu thức cho phương thức khác?

public static Expression<Func<Invoice, CustomerContact>> GetCustomerContact() 
{ 
    return i => new CustomerContact { 
       FirstName = i.Customer.FirstName, 
       LastName = i.Customer.LastName, 
       Email = i.Customer.Email, 
       TelMobile = i.Customer.TelMobile, 
       }; 
} 

Trong các bộ phận khác của mã này, tôi muốn nhận được cùng một đối tượng nhẹ CustomerContact, chỉ không phải từ hóa đơn, nhưng từ khách hàng riêng của mình. Vì vậy, điều hiển nhiên phải làm là nên có:

public static Expression<Func<Customer, CustomerContact>> GetCustomerContact() 
{ 
    return c => new CustomerContact { 
       FirstName = c.FirstName, 
       LastName = c.LastName, 
       Email = c.Email, 
       TelMobile = c.TelMobile, 
       }; 
} 

và sau đó thay đổi Expression tham Invoice như là đầu vào để đề cập đến phương pháp này, tức là một cái gì đó như thế này:

public static Expression<Func<Invoice, CustomerContact>> GetCustomerContact() 
{ 
    return i => GetCustomerContact(i.Customer); // doesn't compile 
} 

là gì cú pháp chính xác cho điều này?

+2

Sẽ hữu ích nếu bạn đăng lỗi. –

+0

@newStackExchangeInstance: "Phương pháp, đại biểu hoặc sự kiện được mong đợi" –

Trả lời

3

Bạn có thể sử dụng Expression.Invoke:

var paramExpr = Expression.Parameter(typeof(Invoice), "i"); 
var propertyEx = Expression.Property(paramExpr, "Customer"); 

var body = Expression.Invoke(GetCustomerContactFromCustomer(), propertyEx); 

return Expression.Lambda<Func<Invoice, CustomerContact>>(body, paramExpr); 

Do lưu ý rằng một số nhà cung cấp LINQ có vấn đề với ví dụ gọi-biểu thức.

Cách dễ nhất để làm việc xung quanh này (và cung cấp cho bạn cú pháp thuận tiện hơn) là sử dụng LINQKit:

var expr = GetCustomerContactFromCustomer(); 
Expression<Func<Invoice, CustomerContact>> result = i => expr.Invoke(i.Customer);  
return result.Expand(); 
+0

Ouch, điều đó khá không phù hợp. Có lẽ đó là giải pháp tốt nhất, nhưng tôi đã hy vọng sẽ có một giải pháp đơn giản hơn không liên quan đến sự phản chiếu hoặc phần mở rộng của bên thứ ba ... –

+0

Tôi không nghĩ có cách nào dễ hơn Expression.Invoke để soạn biểu thức trong cách thức. Cách LINQKIt mặc dù khá đơn giản và thanh lịch và mang lại cho bạn khả năng sử dụng ngôn ngữ lambdas cho việc này. – Ani

+0

Vâng, hóa ra LinqKit sẽ hữu ích cho dự án của tôi ở các khu vực khác. Vì vậy, cảm ơn và trả lời tín dụng cho bạn! :-) –

0

Bạn có chắc chắn bạn cần phải sử dụng một Expression? Nếu bạn không cần các nhà cung cấp LINQ khác nhau để chuyển đổi cây mã thành các truy vấn, thì hãy cân nhắc chỉ sử dụng Func. Nếu bạn chỉ cần sử dụng Func sao cho chữ ký phương pháp là:

public static Func<Customer, CustomerContact> GetCustomerContact(); 

public static Func<Customer, CustomerContact> GetCustomerContact(); 

Sau đó, cú pháp của bạn sẽ tốt cho xây dựng thứ hai Func tắt của cái đầu tiên. Tất nhiên, điều này sẽ chỉ làm việc cho các đối tượng trong bộ nhớ (với LINQ-to-đối tượng).

Vấn đề là để xây dựng một Expression, bạn phải xây dựng một cách rõ ràng cây đánh giá, có thể khá lông (sử dụng các phương pháp tĩnh khác nhau trên Expression). Bởi vì độ xù lông này, có một số gói trợ giúp, bao gồm LINQKit.

+0

Vâng, tôi cần một Biểu thức; Tôi muốn truy vấn chạy SQL-side. –

+0

Sau đó, đi với giải pháp của Ani! –