2010-05-05 18 views
7

我想重寫Html.TextBoxFor()與我自己的幫助具有完全相同的簽名(但當然不同的名稱空間) - 這是可能的,如果是這樣,如何?ASPNET MVC - 使用具有相同簽名的新助手重寫Html.TextBoxFor(model.property)?

原因是我在已存在的應用程序中有100多個視圖,並且我想要更改TextBoxFor的行爲,以便在屬性具有[StringLength(n)]時輸出maxLength = n屬性註解。

自動輸出maxlength = n的代碼在這個問題中:maxlength attribute of a text box from the DataAnnotations StringLength in Asp.Net MVC。但我的問題不是重複的 - 我想創建一個更通用的解決方案:DataAnnotaion自動流入html,而不需要編寫視圖的人額外編寫代碼。

在引用的問題中,您必須將每個Html.TexBoxFor更改爲Html.CustomTextBoxFor。我需要這樣做,以便現有的TextBoxFor()不需要改變 - 因此創建一個具有相同簽名的助手:改變助手方法的行爲,並且所有現有的實例將不加改變地工作(100 +視圖,至少500個TextBoxFor()s - 不想手動編輯)。

我試過這段代碼:(我需要重複它TextBoxFor的每個過載,但一旦根源問題得到解決,這將是微不足道的)

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 
     } 
    } 
} 

但我得到一個編譯器錯誤Html.TextBoxFor()上的視圖:「該調用在以下方法或屬性之間不明確」(當然)。有沒有辦法做到這一點?

是否有替代方法可以讓我改變Html.TextBoxFor的行爲,以便已經使用它的視圖不需要改變?

+3

Visual Studio的查找和替換是相當強大的。它可以用'Html.CustomTextBoxFor'只需點擊一下就可以代替'Html.TextBoxFor'解決方案中的所有事件!您不需要手動編輯任何文件以重命名方法。 – CoderDennis 2011-06-21 14:46:50

回答

-3

您可以使用editortemplate和自定義的ModelMetadataProvider解決此問題。 (對不起,沒有提供更多的信息,雖然這是相當Googleable,我希望這會讓你在正確的方向。)

+0

他仍然需要用'EditorFor'替換所有的'TextBoxFor'。 – 2010-05-05 08:52:39

+1

爲什麼不只是提供一個鏈接? – Dan 2010-06-14 14:25:47

4

你不能有兩個同時具有相同名稱和相同簽名的擴展方法。你可以把你的擴展方法到一個自定義命名空間和在你的web.config使用此命名空間,而不是默認的(System.Web.Mvc.Html):

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

,但如果你這樣做,你將失去一切其他擴展方法,您將需要在自定義名稱空間中覆蓋它們。

+0

您是否認爲這不是刪除System.Web.Mvc。Html我可以將其別名(ala使用Foo =命名空間),然後對於我不需要重寫的所有方法,我可以直接去: YourCompany.Web.Mvc.Html LabelFor(args) { 返回Foo.LabelFor(args); } ? – 2010-05-05 21:43:22

+0

嗨Darin,我同意在這種特殊情況下,覆蓋擴展似乎是不可能的。但我不同意你的陳述,即「你不能同時使用兩個同名同名簽名的擴展方法。」如果您將擴展方法放在消費類的相同命名空間中(或者層次結構中只有少量名稱空間),那麼它非常可能。在下面的文章中有一個例子:http://stackoverflow.com/questions/6688613/is-there-any-other-way-to-implement-overriding-not-virtual-and-override-in-cs/6688687#6688687 – 2013-02-12 22:25:48

1

簡而言之,不,您不能「替換」現有的擴展方法。

較長的答案,你可能能夠通過一些非常邪惡的反思來做到這一點......雖然我高度懷疑,即使這將工作。沿着這些線:

 // 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);     
       } 
      } 
     } 
相關問題