そのため、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");
この場合、コンパイラは最も近い一致を選択すると本当に思ったので、HtmlExtensions Id メソッドが呼び出されるよりも HtmlElement から継承する Script クラスがある場合、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
ありがとう、
ピーター