所以我有一个对象层次结构来在 asp.net mvc 中生成 ui 控件并尝试实现流畅的 api。我做了一些虚拟课程来专注于当前的问题。
所以这是“错误”的代码库:
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 上调用 Id 时,编译器会说存在模棱两可的调用:
LinkButton lb = new LinkButton().Id("asd");
我真的认为编译器在这种情况下会选择最接近的匹配,所以如果我有一个从 HtmlElement 继承的 Script 类而不是调用 HtmlExtensions Id 方法,并且对于 LinkButton(由于限制),将调用 ButtonBase 方法。我有一个解决方案,但我不确定是否有更好的解决方案。
我从 ButtonBaseExtensions 中删除了 Id 方法,并按以下方式修改了 HtmlElementExtensions Id 方法:
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 论坛上启动了一个主题:链接
我尝试了一些非通用扩展方法:
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
谢谢,
彼得