需求:根據資料庫欄位值 (字串) 動態建立對應的 `UserControl` (如 `ctl_user`),加入 `Panel` 顯示。使用反射 `Assembly.CreateInstance` 依類別全名實例化。
// 假設命名空間為 MyApp.Controls
string controlTypeName = "MyApp.Controls.ctl_user"; // 可從資料庫讀取
Control ctl = Assembly.GetExecutingAssembly().CreateInstance(controlTypeName) as Control;
if (ctl != null) {
ctl.Dock = DockStyle.Fill;
panelMain.Controls.Add(ctl);
} else {
MessageBox.Show("找不到控件類型: " + controlTypeName);
}
public void LoadControl(string typeName, Panel container) {
container.Controls.Clear();
try {
// 支援 "ctl_user" 短名,自動補全命名空間
string fullName = typeName.Contains(".") ? typeName : "MyApp.Controls." + typeName;
Control ctl = Assembly.GetExecutingAssembly().CreateInstance(fullName) as Control;
if (ctl == null) throw new Exception("類型不存在或非 Control");
ctl.Dock = DockStyle.Fill;
container.Controls.Add(ctl);
} catch (Exception ex) {
MessageBox.Show("動態載入失敗: " + ex.Message);
}
}
// 使用
LoadControl("ctl_user", panelMain); // 短名
LoadControl("MyApp.Controls.ctl_admin", panelMain); // 全名
| 要點 | 說明 |
|---|---|
| 命名空間一致 | 字串必須為「命名空間.類別名」,區分大小寫 |
| 類別繼承 Control | UserControl 間接繼承 Control,可直接轉型 |
| Dock = Fill | 確保控件填滿容器 Panel |
| Clear 再 Add | 避免重複疊加舊控件 |
| 異常處理 | 類型錯誤、缺少建構子、存取層級皆可能失敗 |
Dispose()` 釋放資源 (事件解綁、計時器停止)。
public void LoadControl(Panel container) where T : Control, new() {
container.Controls.Clear();
var ctl = new T { Dock = DockStyle.Fill };
container.Controls.Add(ctl);
}
// 使用:LoadControl(panelMain);
若類型在編譯期已知,泛型版本更安全、效能更高;僅在類型完全由執行期字串決定時用反射。