管理者がユーザーに表示されるさまざまなデータ入力フォームをカスタマイズできる .NET Web アプリケーションを作成しています。管理者が作成およびカスタマイズできる約 6 種類のフィールド タイプ (テキスト、数値、ドロップダウン、ファイル アップロードなど) があります。すべてのフィールドは、一連の基本属性/動作を共有します (フィールドは必須ですか? デフォルトのフィールド値はありますか?)。一連のフィールド固有の属性/動作もあります (つまり、ドロップダウンにはデータ ソース属性がありますが、テキスト フィールドにはありません)。簡単にするために、問題領域の他の多くの特徴を省略しています。
クラス階層は単純です。一般的な動作/属性をカプセル化する抽象的なスーパークラスと、フィールド固有のものを処理する約半ダースの具体的なサブクラスです。
各フィールド タイプは、特定のタイプの .NET サーバー コントロールとしてレンダリング (マップ) されます。これらはすべて System.Web.UI.Control から派生します。
フィールド ドメイン オブジェクトとそれに対応する UI コントロールの間で値をマッピングするために、次のコードを作成しました。
public static void Bind(Control control, IList<DocumentFieldBase> fieldBaseList)
foreach (DocumentFieldBase fieldBase in fields){
if (typeof (DocumentFieldText).IsInstanceOfType(fieldBase)){
TextBox textbox = (TextBox) control;
textbox.Text = (fieldBase as DocumentFieldText).GetValue();
}
if (typeof (DocumentFieldDropDown).IsInstanceOfType(fieldBase)){
DropDown dropDown= (DropDown) control;
dropDown.Text = (fieldBase as DocumentFieldSelectOne).GetValue().Text;
dropDown.DataSource= (fieldBase as DocumentFieldSelectOne).DataSource;
dropDown.Id= (fieldBase as DocumentFieldSelectOne).GetValue().Id;
}
//more if statements left out for brevity
}
}
型チェックを実行する無礼な if ステートメントを捨てたいと思います。私が目指していたアプローチは、サブクラスの型付けを使用して、フィールド/コントロールの組み合わせごとにメソッドのオーバーロードを作成することでした。例えば:
public static void Bind(TextBox control, DocumentFieldText fieldText){
//some implementation code
}
public static void Bind(DropDown control, DocumentFieldDropDown fieldDropDown){
//some implementation code
}
次に、.NET に依存して、使用されている特定のサブクラスを使用して、実行時に適切なオーバーロードを呼び出すことができることを期待していました。たとえば、次のようになります。
foreach (DocumentFieldBase field in fields){
Control control = FindControl(field.Identifier);
Bind(control, field)
}
残念ながら、次のようにしようとすると、コンパイラがチョークします: Argument '1': cannot convert from 'System.Web.UI.Control' to 'TextBox'.
最初の引数を TextBox にキャストする必要がある場合は、自分で型チェックを実行することに戻り、この演習の目的全体を無効にします。
私が達成しようとしていることは、a) 可能で、b) 良いアイデアですか?