2010-05-05 24 views
7

Tôi muốn ghi đè lên Html.TextBoxFor() với trình trợ giúp của chính tôi có chữ ký chính xác giống nhau (nhưng không gian tên khác nhau) - điều này có thể, và nếu có thì làm cách nào?ASPNET MVC - Ghi đè Html.TextBoxFor (model.property) với trình trợ giúp mới có cùng chữ ký?

Lý do cho điều này là tôi có hơn 100 lượt xem trong một ứng dụng đã tồn tại và tôi muốn thay đổi hành vi của TextBoxFor để nó xuất ra thuộc tính maxLength = n nếu thuộc tính có [StringLength (n)] chú thích.

Mã để tự động xuất maxlength = n là trong câu hỏi này: maxlength attribute of a text box from the DataAnnotations StringLength in Asp.Net MVC. Nhưng câu hỏi của tôi không phải là một bản sao - tôi đang cố gắng tạo một giải pháp chung chung hơn: nơi DataAnnotaion tự động chuyển vào html mà không cần mã bổ sung bởi người viết chế độ xem.

Trong câu hỏi được tham chiếu, bạn phải thay đổi mọi Html.TexBoxFor đơn lẻ thành Html.CustomTextBoxFor. Tôi cần phải làm như vậy để TextBoxFor() hiện tại không cần phải thay đổi - do đó tạo ra một helper có cùng chữ ký: thay đổi hành vi của phương thức helper, và tất cả các cá thể hiện tại sẽ hoạt động mà không có bất kỳ thay đổi nào (100 + lượt xem, ít nhất 500 TextBoxFor() s - không muốn chỉnh sửa thủ công).

Tôi đã thử mã này: (Và tôi cần phải lặp lại nó cho mỗi tình trạng quá tải của TextBoxFor, nhưng một khi vấn đề gốc được giải quyết, đó sẽ là tầm thường)

namespace My.Helpers 
{ 
    public static class CustomTextBoxHelper 
    { 
     public static MvcHtmlString TextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression, object htmlAttributes, bool includeLengthIfAnnotated) 
     { 
       // implementation here 
     } 
    } 
} 

Nhưng tôi nhận được một lỗi biên dịch trong chế độ xem trên Html.TextBoxFor(): "Cuộc gọi không rõ ràng giữa các phương thức hoặc thuộc tính sau" (tất nhiên). Có cách nào để làm điều này không?

Có cách tiếp cận thay thế nào cho phép tôi thay đổi hành vi của Html.TextBoxFor, sao cho các chế độ xem đã sử dụng không cần phải thay đổi?

+3

Tìm và thay thế của Visual Studio khá mạnh mẽ. Nó có thể thay thế tất cả các lần xuất hiện trong Giải pháp 'Html.TextBoxFor' của bạn bằng' Html.CustomTextBoxFor' chỉ bằng một cú nhấp chuột! Bạn không bao giờ cần chỉnh sửa thủ công bất kỳ tệp nào để đổi tên phương thức. – CoderDennis

Trả lời

-3

Bạn có thể giải quyết vấn đề này bằng bảng chỉnh sửa và ModelMetadataProvider tùy chỉnh. (Xin lỗi vì không cung cấp thêm thông tin, mặc dù điều này khá thông minh và tôi hy vọng điều này sẽ đưa bạn đi đúng hướng.)

+0

Anh ta vẫn cần phải thay thế tất cả 'TextBoxFor' bằng' EditorFor'. –

+1

Tại sao không chỉ cung cấp liên kết? – Dan

4

Bạn không thể có hai phương thức mở rộng có cùng tên và cùng một chữ ký cùng một lúc. Bạn có thể đưa phương pháp mở rộng của bạn thành một không gian tên tùy chỉnh và sử dụng không gian tên này thay vì một mặc định (System.Web.Mvc.Html) trong web.config của bạn:

<pages> 
    <namespaces> 
     <!--<add namespace="System.Web.Mvc.Html"/>--> 
     <add namespace="YourCompany.Web.Mvc.Html"/> 
    </namespaces> 
</pages> 

nhưng nếu bạn làm điều này bạn sẽ mất tất cả các phương thức mở rộng khác và bạn sẽ cần ghi đè chúng trong không gian tên tùy chỉnh của mình.

+0

Bạn có nghĩ rằng thay vì xóa System.Web.Mvc.Html tôi có thể bí danh nó với cái gì khác (ala sử dụng Foo = không gian tên), và sau đó cho tất cả các phương pháp mà tôi không cần phải ghi đè lên, tôi chỉ có thể đi: YourCompany.Web.Mvc.Html LabelFor (args) { trả về Foo.LabelFor (args); } ? –

+0

Xin chào Darin, tôi đồng ý rằng trong trường hợp đặc biệt này, việc ghi đè một phần mở rộng dường như không thể thực hiện được. Nhưng tôi không đồng ý với tuyên bố của bạn rằng "Bạn không thể có hai phương pháp mở rộng có cùng tên và cùng một chữ ký cùng một lúc." Nếu bạn đặt phương thức mở rộng của bạn trong cùng một không gian tên (hoặc ít không gian tên trong phân cấp) của lớp tiêu thụ của bạn, nó rất có thể xảy ra. Có một ví dụ thực hiện nó trong bài viết sau: http://stackoverflow.com/questions/6688613/is-there-any-other-way-to-implement-overriding-not-virtual-and-override-in-cs/6688687 # 6688687 –

1

Câu trả lời ngắn gọn, không, bạn không thể "thay thế" phương thức tiện ích mở rộng hiện tại.

Câu trả lời dài hơn, bạn có thể có thể làm như vậy bằng một số phản chiếu cực kỳ ác ... Mặc dù tôi rất nghi ngờ ngay cả điều này cũng có hiệu quả. Một cái gì đó dọc theo các dòng này:

 // Get the handle for the RuntimeMethodInfo type 
     var corlib = Assembly.GetAssembly(typeof (MethodInfo)); 
     var corlibTypes = corlib.GetModules().SelectMany(mod => mod.FindTypes((a, b) => true, null)); 
     Type rtmiType = corlibTypes.Where(t => t != null && t.FullName != null && t.FullName.Contains("Reflection.RuntimeMethodInfo")).First(); 

     // Find the extension method 
     var methods = typeof (Html).GetMethods(BindingFlags.Static | BindingFlags.Public); 
     foreach (var methodInfo in methods) 
     { 
      if (methodInfo.Name == "TextBoxFor") 
      { 
       // Try to monkeypatch this to be private instead of public 
       var methodAttributes = rtmiType.GetField("m_methodAttributes", BindingFlags.NonPublic | BindingFlags.Instance); 
       if(methodAttributes != null) 
       { 
        var attr = methodAttributes.GetValue(methodInfo); 
        attr = ((MethodAttributes)attr) | MethodAttributes.Private; 
        methodAttributes.SetValue(methodInfo, attr);     
       } 
      } 
     } 
Các vấn đề liên quan