所以我有一個對象層次結構在asp.net mvc中生成ui控件並嘗試實現流暢的api。我做了一些虛擬課,專注於當前的問題。
因此,這裏是「錯誤」的基本代碼:如何在.NET中「重寫」擴展方法?
public abstract class HtmlElement { /* ... */ }
public abstract class UIElement : HtmlElement { /* ... */ }
public abstract class ButtonBase : UIElement { /* ... */ }
public class LinkButton : ButtonBase { /* ... */ }
public class ActionButton : ButtonBase { /* ... */ }
public static class HtmlElementExtensions
{
public static T Id<T>(this T item, string id) where T : HtmlElement
{
/* set the id */
return item;
}
}
public static class ButtonBaseExtensions
{
public static T Id<T>(this T item, string id) where T : ButtonBase
{
/* set the id and do some button specific stuff*/
return item;
}
}
當我嘗試撥打標識上一個LinkButton編譯器說有曖昧電話:
LinkButton lb = new LinkButton().Id("asd");
我真的以爲編譯器選擇在這種情況下最接近的匹配,所以如果我有一個從HtmlElement繼承的Script類而不是HtmlExtensions Id方法調用,並且對於LinkButton(因爲有限制),ButtonBase方法將被調用。 我有一個解決方案,但我不確定是否有更好的解決方案。
我刪除ButtonBaseExtensions的標識方法和改進的HtmlElementExtensions標識方法,方式如下:
public static T Id<T>(this T item, string id) where T : HtmlElement
{
if (item is ButtonBase)
{
/* do some button specific stuff*/
}
/* set the id */
return item;
}
這樣,從在ButtonBase每類傳人工作。 我不喜歡我的解決方案,因爲它將HtmlElement邏輯與ButtonBase邏輯混合在一起。 任何想法/建議更好的解決方案? 我以爲我把它們放在不同的命名空間,但只是一秒鐘。我應該使用兩個名稱空間,所以不要解決問題。
你認爲在msdn論壇上值得一提的是編譯器應該關注通用擴展方法的限制嗎?
在此期間我做一些更多的研究,並在MSDN論壇啓動一個線程:link
我嘗試了一些非通用擴展methodds:
public class BaseClass { /*...*/ }
public class InheritedClass : BaseClass { /*...*/ }
public static class BaseClassExtensions
{
public static void SomeMethod(this BaseClass item, string someParameter)
{
Console.WriteLine(string.Format("BaseClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}
public static class InheritedClassExtensions
{
public static void SomeMethod(this InheritedClass item, string someParameter)
{
Console.WriteLine(string.Format("InheritedClassExtensions.SomeMethod called wtih parameter: {0}", someParameter));
}
}
如果我舉例說明這些:
BaseClass bc = new BaseClass();
InheritedClass ic = new InheritedClass();
BaseClass ic_as_bc = new InheritedClass();
bc.SomeMethod("bc");
ic.SomeMethod("ic");
ic_as_bc.SomeMethod("ic_as_bc");
產生此輸出:
BaseClassExtensions.SomeMethod called wtih parameter: bc
InheritedClassExtensions.SomeMethod called wtih parameter: ic
BaseClassExtensions.SomeMethod called wtih parameter: ic_as_bc
個
感謝,
彼得
擴展方法是** **不爲虛方法的替代品,也不能發虛。考慮到你自己宣佈了這些課程,爲什麼你需要它,這是相當不清楚的。只需將一個虛擬方法添加到其中一個基類中,並在必要時在派生類中重寫它。 – 2013-04-22 11:11:58
由於流利的API,我必須使用擴展方法。泛型繼承僅適用於2級繼承。 我寫了一個非genric擴展方法的示例,其中編譯器使用參數限制來確定調用的正確方法。我只希望編譯器也評估通用參數限制。我不能寫「公共靜態ButtonBase ID(這ButtonBase項目,字符串ID)」而不是「公共靜態T Id(這T項目,字符串ID)其中T:ButtonBase」,因爲返回類型將ButtonBase和它破流利api的方法鏈。 –
2013-04-22 13:58:02