首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

WinForms 統一控制項驗證框架(一):核心架構與反射工廠模式

     編輯:關於.NET

功能清單

  1. 輸入前鎖定非關鍵控制項
  2. 必填欄位空值驗證
  3. 輸入格式正則驗證
  4. 一鍵清空畫面
  5. 設定控制項預設值
  6. 清除錯誤提示訊息
  7. 資料列 → 編輯控制項 映射
  8. 編輯控制項 → 資料列 回寫

核心實體:SetControl

public class SetControl
{
    [Description("控制項名稱")] public object ControlName { get; set; }
    [Description("可否為空")] public bool NullAble { get; set; }
    [Description("預設值")] public object Default { get; set; }
    [Description("匹配格式(Regex)")] public string Format { get; set; }
    [Description("是否主鍵")] public bool KeyFiled { get; set; }
    [Description("對應欄位名稱")] public string FiledName { get; set; }

    public override string ToString() {
        var prop = ControlName.GetType().GetProperty("Name");
        return prop?.GetValue(ControlName, null)?.ToString() ?? "";
    }
}

抽象操作介面:TypeProcess

public abstract class TypeProcess
{
    protected SetControl _setCtrl;
    protected TypeProcess(SetControl sender) { _setCtrl = sender; }

    public abstract bool CheckNull();
    public abstract bool CheckFormat();
    public abstract void SetCtrlClear();
    public abstract void SetCtrlEnable(bool enable);
    public abstract void SetCtrlDefault();
    public abstract void ClearErrText();
    public abstract void LoadToText(DataRow row);
    public abstract void SetTextToRow(DataRow row);
}

具體實作範例

TextEditProcess (DevExpress TextEdit)

public class TextEditProcess : TypeProcess
{
    DevExpress.XtraEditors.TextEdit txt;
    public TextEditProcess(SetControl sender) : base(sender) { txt = _setCtrl.ControlName as DevExpress.XtraEditors.TextEdit; }

    public override bool CheckNull() {
        if (!_setCtrl.NullAble && string.IsNullOrWhiteSpace(txt.Text)) {
            txt.ErrorText = "不能為空"; txt.Focus(); return false;
        } return true;
    }
    public override bool CheckFormat() {
        if (!string.IsNullOrEmpty(_setCtrl.Format) && !Regex.IsMatch(txt.Text, $"^{_setCtrl.Format}$")) {
            txt.ErrorText = "輸入格式不正確"; txt.Focus(); return false;
        } return true;
    }
    public override void SetCtrlClear() => txt.EditValue = null;
    public override void SetCtrlEnable(bool enable) => txt.Enabled = _setCtrl.KeyFiled ? enable : !enable;
    public override void SetCtrlDefault() => txt.EditValue = _setCtrl.Default;
    public override void ClearErrText() => txt.ErrorText = string.Empty;
    public override void LoadToText(DataRow row) { if (!string.IsNullOrEmpty(_setCtrl.FiledName)) txt.EditValue = row[_setCtrl.FiledName]; }
    public override void SetTextToRow(DataRow row) { if (!string.IsNullOrEmpty(_setCtrl.FiledName)) row[_setCtrl.FiledName] = txt.EditValue; }
}

ComboBoxEditProcess

public class ComboBoxEditProcess : TypeProcess
{
    DevExpress.XtraEditors.ComboBoxEdit comb;
    public ComboBoxEditProcess(SetControl sender) : base(sender) { comb = _setCtrl.ControlName as DevExpress.XtraEditors.ComboBoxEdit; }
    public override bool CheckNull() { /* 檢查 EditValue 是否為 null */ }
    public override bool CheckFormat() => true; // 下拉選單通常不需格式驗證
    // 其他方法類似 TextEditProcess,操作 comb.EditValue
}

反射工廠與快取

public class TypeFactory
{
    public static TypeProcess CreateType(string type, object[] obj, string ctrlCnm, TypeCache cache)
    {
        if (cache.ExistObject(ctrlCnm)) return cache.GetObject(ctrlCnm) as TypeProcess;
        var process = (TypeProcess)Assembly.Load("RealSailing.BizControls")
            .CreateInstance($"RealSailing.UI.Utils.{type}Process", false, BindingFlags.Default, null, obj, new CultureInfo("zh-CN"), null);
        cache.AddObject(ctrlCnm, process);
        return process;
    }
}

public class TypeCache
{
    readonly Hashtable htObj = Hashtable.Synchronized(new Hashtable());
    public void AddObject(string name, object instance) { if (!htObj.ContainsKey(name)) htObj.Add(name, instance); }
    public void DeleteObject(string name) { if (htObj.ContainsKey(name)) htObj.Remove(name); }
    public object GetObject(string name) => htObj.ContainsKey(name) ? htObj[name] : null;
    public bool ExistObject(string name) => htObj.ContainsKey(name);
    public void ClearObject() => htObj.Clear();
}

統一入口:ControlValidation

public class ControlValidation
{
    readonly TypeCache typeCache = new TypeCache();
    List ctrlCollect = new List();
    public List CtrlCollect { get => ctrlCollect; set => ctrlCollect = value; }

    // 8 大公開方法皆採相同模式:遍歷 ctrlCollect → TypeFactory.CreateType → 呼叫對應 TypeProcess 方法
    // 範例:
    public bool CheckIsNull() {
        foreach (var ctrl in ctrlCollect) {
            var proc = TypeFactory.CreateType(ctrl.ControlName.GetType().Name, new object[]{ctrl}, ctrl.ToString(), typeCache);
            if (!proc.CheckNull()) return false;
        } return true;
    }
    // ... CheckIsFormat, SetCtrlClear, SetCtrlEnable, SetCtrlDefault, ClearErrText, LoadEditRowToText, SetCtrlTextToEditRow
}

使用範例

ControlValidation validate = new ControlValidation();
void Init() {
    validate.CtrlCollect = new List {
        new SetControl { ControlName=CombRegionType, FiledName="MSTM030_REGIONTYPE", Default=null, KeyFiled=true, NullAble=false, Format="" },
        new SetControl { ControlName=txtRegionCd, FiledName="MSTM030_REGIONCD", Default=null, KeyFiled=true, NullAble=false, Format="" },
        new SetControl { ControlName=CombCompanyId, FiledName="MSTM030_COMID", Default=null, KeyFiled=false, NullAble=true, Format="" }
    };
}
// 於 Form Load 或建構函數呼叫 Init()
// 之後即可隨時呼叫 validate.SetCtrlClear()、validate.CheckIsNull() 等

架構優勢

  • 開放封閉原則:新增控制項型別只需增加對應 XXXProcess 類別
  • 反射工廠解耦:主邏輯不依賴具體控制項型別
  • 實例快取:避免重複建立 TypeProcess 物件
  • 統一介面:8 大功能一致性呼叫
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved