專案需對 8 類學生資訊 (基本、家庭、獎學金、活動、資助、處分、素質測評、比賽) 進行 CRUD,每類對應一資料表、一實體、一 WinForm 編輯視窗。透過繼承基底表單 Form_Base 並定義虛擬方法 ConstructEntityInfo(),實現「統一流程、個別實作」的多型架構。
Form_Base 核心邏輯public partial class Form_Base : Form
{
protected StudentManagerDataContext Context { get; private set; }
protected DataGridView GridView { get; set; } // 回寫清單
protected object Entity { get; set; } // 編輯時的實體
protected bool IsEdit { get; private set; }
public Form_Base() { }
public Form_Base(object entity)
{
if (entity != null) { IsEdit = true; Entity = entity; }
Context = new StudentManagerDataContext(AppInfo.ConnectionString);
}
// 統一的新增/修改流程
protected void AddOrEditInfo()
{
try
{
if (ISLegal())
{
ConstructEntityInfo(); // 多型進入點
SMSApplication.ShowOperateSucceedResult();
}
else ShowHandleEntityError(null);
}
catch (FormatException ex) { /* 格式錯誤友善提示 */ }
catch (OverflowException ex) { /* 溢位錯誤友善提示 */ }
catch (Exception ex) { ShowHandleEntityError(ex.Message); }
finally { this.Dispose(); }
}
// 由子類實作具體實體建構/更新邏輯
protected virtual void ConstructEntityInfo()
{
throw new NotImplementedException();
}
protected bool ISLegal() => DataPool.StudentNumber != "0";
// ... 錯誤處理輔助方法
}
Form_Gamepublic partial class Form_Game : Form_Base
{
private Game game = new Game();
public Form_Game(DataGridView view, object entity) : base(entity)
{
GridView = view; Entity = entity;
InitializeComponent();
if (IsEdit)
{
game = entity as Game;
dateTimePicker_GameTime.Text = game.GameDateTime.ToString();
textBox_GameName.Text = game.GameName;
textBox_GameResult.Text = game.GameResult;
}
}
private void button_AddGame_Click(object sender, EventArgs e)
{
AddOrEditInfo(); // 呼叫基底統一流程
}
protected override void ConstructEntityInfo()
{
if (IsEdit)
game = (from g in Context.Games where g.GameID == ((Game)Entity).GameID select g).Single();
game.GameResult = textBox_GameResult.Text;
game.GameName = textBox_GameName.Text;
game.GameDateTime = Convert.ToDateTime(dateTimePicker_GameTime.Text);
if (!IsEdit)
{
game.StudentNumber = DataPool.StudentNumber;
Context.Games.InsertOnSubmit(game);
}
Context.SubmitChanges();
GridView.DataSource = GetIQueryable.GetGameQueryable(Context);
}
}
Form_Supportpublic partial class Form_Support : Form_Base
{
private StudentSupport support = new StudentSupport();
public Form_Support(DataGridView gridview, object entity) : base(entity)
{
GridView = gridview; Entity = entity;
InitializeComponent();
if (IsEdit)
{
support = entity as StudentSupport;
dateTimePicker_SupportTime.Text = support.SupportTime.ToShortDateString();
textBox_SupportAmount.Text = support.SupportAmount.ToString();
textBox_SupportRemark.Text = support.SupportRemark;
textBox_SupportSource.Text = support.SupportFrom;
}
}
private void button_AddSupport_Click(object sender, EventArgs e) => AddOrEditInfo();
protected override void ConstructEntityInfo()
{
if (IsEdit)
support = (from s in Context.StudentSupports where s.SupportID == ((StudentSupport)Entity).SupportID select s).Single();
support.SupportAmount = Convert.ToInt32(textBox_SupportAmount.Text);
support.SupportFrom = textBox_SupportSource.Text;
support.SupportRemark = textBox_SupportRemark.Text;
support.SupportTime = Convert.ToDateTime(dateTimePicker_SupportTime.Text);
if (!IsEdit)
{
support.StudentNumber = DataPool.StudentNumber;
Context.StudentSupports.InsertOnSubmit(support);
}
Context.SubmitChanges();
GridView.DataSource = GetIQueryable.GetSupportQueryable(Context);
}
}
ConstructEntityInfo,不修改基底。GridView = view; Entity = entity; 移至基底建構子,避免子類重複賦值。Context 操作,降低對 LINQ to SQL 的耦合。IEntityEditor 定義編輯契約,配合 DI 容器管理視窗建立。此多型實作展示了「模板方法模式」在 WinForms 資料編輯場景的經典應用,有效平衡了共性流程與個性邏輯。