2011-04-05 37 views
14

Đối với lợi ích của sự đơn giản, hãy tưởng tượng đoạn mã sau:Làm cách nào để nhận giá trị từ biểu thức ẩn danh?

Tôi muốn tạo ra một Foo:

public class Foo 
{ 
    public string Bar { get; set; } 
} 

Và vượt qua nó đến một phương pháp trợ giúp Html đặc biệt:

Html.SomeFunction(f => f.Bar); 

nào được định nghĩa như:

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 

Tôi muốn nhận được giá trị của Thanh bên trong của chức năng này, nhưng hoàn toàn không có ý tưởng làm thế nào để có được nó.

Trả lời

26

Chỉ cần biên dịch biểu thức và nhận giá trị.

Func<TModel, TValue> method = expression.Compile(); 

TValue value = method(html.ViewData.Model); 
// might be a slightly different property, but you can get the ViewModel 
// from the HtmlHelper object. 
+0

Tôi nhận được lỗi sau với mã của bạn: Lỗi 'System.Web.Mvc.HtmlHelper ' không chứa định nghĩa cho 'Mô hình' và không phương pháp mở rộng 'Mô hình' chấp nhận một đối số đầu tiên của loại 'System.Web.Mvc.HtmlHelper ' có thể được tìm thấy (bạn đang thiếu một chỉ thị bằng cách sử dụng hoặc một tham chiếu lắp ráp?) – mynameiscoffey

+2

Nó phải là 'html.ViewData.Model'. Bài viết đầu tiên của tôi đơn giản là vội vàng với tên thuộc tính. – Tejs

+0

+1 Làm việc như một sự quyến rũ, cảm ơn !! – mynameiscoffey

5

Bạn sẽ cần gọi số Compile() trên biểu thức để nhận Func và sau đó thực hiện điều đó.

public string SomeFunction<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression) 
{ 
    TValue valueOfBar = expression.Compile()(html.Model); // Assumes Model is accessible from html. 

    // Do stuff 
} 

Lưu ý phụ: Nếu không cần phân tích biểu thức hoặc biểu thức động, bạn cũng có thể chuyển trực tiếp Func.

+1

+1 Reddog cũng nói sự thật ở đây; nếu thực sự không có lý do nào để kiểm tra biểu thức, thì chỉ cần truyền 'Func ' là tốt hơn nhiều. – Tejs

+1

Rất tiếc, Biểu thức là bắt buộc đối với các tương tác khác xảy ra trong phương thức – mynameiscoffey

0

Đối với những người đang sử dụng biểu thức không có mô hình MVT, người ta sẽ có được tên và giá trị của thuộc tính theo cách sau.

public static string Meth<T>(Expression<Func<T>> expression) 
{ 
    var name = ((MemberExpression)expression.Body).Member.Name; 
    var value = expression.Compile()(); 
    return string.Format("{0} - {1}", name, value); 
} 

sử dụng:

Meth(() => YourObject.Property); 
0

Sử dụng Compile() sẽ sử dụng trình biên dịch Roslyn-framework và sẽ phát ra MSIL mã đó sẽ được tự động nạp vào ứng dụng của bạn. Mã thực thi này chiếm bộ nhớ và ngược lại với bộ nhớ "bình thường", nó không phải là bộ sưu tập rác và bạn cũng không thể tự giải phóng nó. Nếu bạn làm điều này quá thường xuyên (như thường xuyên trong quá trình tạo SQL) thì cuối cùng bạn sẽ hết bộ nhớ. Tôi chạy vào vấn đề này và mã nguồn mở giải pháp của tôi như là một thư viện mã nguồn mở:

https://www.nuget.org/packages/MiaPlaza.ExpressionUtils

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