WinForms/WebForms 開發中,大量重複的「控制項 ←→ 實體屬性」賦值程式碼不僅冗長,還易出錯。本文提出一套基於命名慣例(控制項 ID = 前綴 + 屬性名)與反射的通用綁定機制,並透過介面統一存取 WinForms/WebForms 控制項,實現 UI 與後端邏輯解耦。
txtName ↔ User.Name、drpRole ↔ User.Role。前綴對應表:TextBox=txt、DropDownList=drp、ComboBox=cmb、Hidden=hdn、CheckBox=chk。RealCtl、GetCtlID()、GetSubCtls(),分別實作 WebControl、WinControl 結構體。Tuple 定義需處理的控制項型別,Iterator 方法遞迴走訪控制項樹並過濾。SetCtlsVal<T>(Control, T entity)、GetCtlsVal<T>(Control, T entity),核心邏輯:entity.GetType().GetProperty(propName).GetValue/SetValue。// 介面與實作
interface IControl { object RealCtl { get; } string GetCtlID(); IEnumerable GetSubCtls(); }
struct WebControl : IControl { /* 封裝 System.Web.UI.Control */ }
struct WinControl : IControl { /* 封裝 System.Windows.Forms.Control */ }
// 遞迴迭代器(簡化版)
IEnumerable Iterate(IControl root, Tuple allowedTypes)
{
foreach (var ctl in root.GetSubCtls())
{
if (!allowedTypes.HasType(ctl.RealCtl))
foreach (var sub in Iterate(ctl, allowedTypes)) yield return sub;
else yield return ctl;
}
}
// 實體 → 控制項(WebForms 範例)
public static void SetCtlsVal(Control root, T entity)
{
var allowed = Tuple.Create(typeof(TextBox), typeof(DropDownList), typeof(HiddenField));
foreach (var ctl in Iterate(new WebControl(root), allowed))
{
string propName = ParseCtlID(ctl.GetCtlID(), GetCtlType(ctl.RealCtl));
object val = typeof(T).GetProperty(propName)?.GetValue(entity);
if (val == null) continue;
switch (ctl.RealCtl)
{
case TextBox tb: tb.Text = val.ToString(); break;
case DropDownList ddl: ddl.SelectedValue = val.ToString(); break;
case HiddenField hf: hf.Value = val.ToString(); break;
}
}
}
class LoginController
{
private Form _view; private User _user = new User();
public LoginController(Form view) { _view = view; }
public bool ValidateInput()
{
ControlHelper.GetCtlsVal(_view, _user); // UI → 實體
return !string.IsNullOrEmpty(_user.Name) && !string.IsNullOrEmpty(_user.Pwd);
}
}
Controller 不依賴具體控制項型別,只操作實體物件,單元測試極易撰寫。
Text = ""。[ReadOnly] 屬性自動鎖定控制項。Panel、GroupBox、UserControl 透過 GetSubCtls() 遞迴處理。[Required]、[StringLength] 於綁定時自動檢查。| 優點 | 缺點/注意 |
|---|---|
| 消除大量樣板碼 | 依賴命名慣例,團隊需嚴格遵守 |
| UI/邏輯解耦,利測試 | 反射效能較差(可快取 PropertyInfo) |
| 支援 WinForms/WebForms 同一套邏輯 | 複雜控制項(Grid、TreeView)需另行處理 |
| 易擴充驗證、樣式、本地化 | 動態產生控制項需確保命名正確 |
此模式在中型專案極具實用價值,將「機械性綁定」交給機器,開發者專注於業務邏輯。