.NET 反射機制允許在運行時根據完整型別名稱(含命名空間、組件資訊)動態載入型別並建立實例。關鍵在於取得正確的 AssemblyQualifiedName。
using System;
using System.Windows.Forms;
using System.Reflection;
public static class ControlFactory
{
///
/// 根據型別名稱動態建立控件並加入表單
///
/// 完整型別名,如 "System.Windows.Forms.TextBox"
/// 目標表單
/// X 座標
/// Y 座標
public static Control CreateControl(string controlType, Form form, int x, int y)
{
try
{
// 1. 取得 Windows Forms 組件完整限定名稱後綴
string assemblyQualifiedName = typeof(Form).AssemblyQualifiedName;
string assemblyInfo = assemblyQualifiedName.Substring(assemblyQualifiedName.IndexOf(','));
// 2. 組合完整型別名稱:TypeName, AssemblyInfo
string fullTypeName = controlType + assemblyInfo;
// 3. 取得 Type 物件
Type type = Type.GetType(fullTypeName);
if (type == null)
throw new ArgumentException($"找不到型別: {controlType}");
// 4. 建立實例
Control ctrl = (Control)Activator.CreateInstance(type);
// 5. 初始化屬性並加入表單
form.SuspendLayout();
ctrl.Location = new System.Drawing.Point(x, y);
ctrl.Name = type.Name + form.Controls.Count;
form.Controls.Add(ctrl);
form.ResumeLayout();
return ctrl;
}
catch (Exception ex)
{
// 實務上應記錄日誌並拋出自訂異常
throw new InvalidOperationException($"動態建立控件失敗: {controlType}", ex);
}
}
}
// 在表單按鈕點擊事件中
private void btnCreate_Click(object sender, EventArgs e)
{
// 動態建立 TextBox
ControlFactory.CreateControl("System.Windows.Forms.TextBox", this, 10, 10);
// 動態建立 Button
ControlFactory.CreateControl("System.Windows.Forms.Button", this, 10, 50);
// 動態建立 DataGridView
ControlFactory.CreateControl("System.Windows.Forms.DataGridView", this, 10, 100);
}
Type.GetType("System.Windows.Forms.TextBox") 會回傳 null,因為 System.Windows.Forms.dll 是強命名組件,存在 GAC 中有多版本。CLR 需完整組件資訊(版本、公開金鑰權杖、文化特性)才能精確載入。
利用專案中已引用的任一 WinForms 型別(如 typeof(Form))取得其 AssemblyQualifiedName,截取逗號後的組件資訊,拼接至目標型別名稱。此法適用於同組件內所有控件。
Dictionary<string, object> 設定控件屬性(Text、Size、Font 等)。GetEvent / AddEventHandler 動態掛載事件。Dictionary<string, Type> 快取已解析型別,提升效能。反射動態建立控件是 .NET 靈活性的經典展現。掌握 AssemblyQualifiedName 組合技巧與 Activator.CreateInstance 流程,即可打破編譯期型別綁定限制,構建高度動態的應用程式。