私はasp.net mvcでUIコントロールを生成し、流暢なAPIを実現しようとするオブジェクト階層を持っています。私は、現在の問題に焦点を当てるためにいくつかのダミークラスを作成します。だからここ
は、「間違った」コードベースである:私はLinkButtonコントロール上イドを呼び出そうとすると.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 lb = new LinkButton().Id("asd");
私は本当にコンパイラが選択することを考えましたこのケースで最も近いのは、HtmlExtensions IdメソッドよりもHtmlElementから継承されたScriptクラスがあり、LinkButton(制限のため)のためにButtonBaseメソッドが呼び出されるということです。 私は解決策を持っていますが、より良い解決策があるかどうかはわかりません。
私はButtonBaseExtensionsからID方式を削除し、次のようにしてHtmlElementExtensions ID方式を変更:ButtonBaseからすべてのクラスの子孫が動作している。この方法を
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;
}
。 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
の
おかげで、
ペーテル
を**ない**仮想メソッドの代わりに、またそれが仮想行うことができます。これらのクラスを自分で宣言したので、なぜあなたが1つ必要なのかははっきりしていません。基本クラスの1つに仮想メソッドを追加し、必要に応じてそれを派生クラスでオーバーライドするだけです。 –
流暢なAPIのため、私は拡張メソッドを使用する必要があります。ジェネリック継承は2レベルの継承でのみ機能します。 コンパイラがパラメータ制限を使用して呼び出す正しいメソッドを決定する非ジェネリック拡張メソッドの例を書きました。私は、コンパイラがジェネリックパラメータの制限を評価することを望みます。戻り値の型がButtonBaseであり、破損するため、public static T Id(このTアイテム、文字列ID)の代わりに "T:ButtonBase"ではなく "public static ButtonBase Id(このButtonBaseアイテム、文字列ID)流暢なAPIのメソッドチェーン。 –