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

Visual Studio DSL 入門 12:狀態機設計器的規則與驗證機制

     編輯:關於.NET

前言

上一節已為狀態機設計器加入 Rule (規則),處理 Transition 的 Label、Condition、Action、Event 四個屬性聯動更新。本節深入探討 VS.NET DSL 提供的規則類型,並導入 Validation (驗證) 機制作為軟性約束的補充。

一、DSL 規則類型總覽

規則屬於硬性約束:在交易 (Transaction) 過程中被動觸發,若條件不符可取消交易、拋出例外,強制阻止不合法操作。

規則類型觸發時機
AddRuleModelElement 或 ElementLink 新增時
ChangeRule元素或關聯屬性變更時
DeletingRule刪除元素/關聯前
DeletedRule刪除元素/關聯後
RolePlayerChangeRule領域關聯一端角色變更時
RolePlayerPositionChangeRule多重關聯中角色位置變更時
TransactionBeginningRule交易開始時
TransactionCommittingRule交易認可時
TransactionRollingBackRule交易回滾時

注意: AddRule、ChangeRule、DeletingRule 等均在交易進行中觸發,此時可攔截並取消交易。

二、硬性約束的另一種實作:屬性值處理器

除了規則,也可重寫屬性處理器的 OnValueChanging/OnValueChanged:

internal sealed partial class ConditionPropertyHandler : DomainPropertyValueHandler<Transition, string>
{
    protected override void OnValueChanging(Transition element, string oldValue, string newValue)
    {
        if (!element.Store.InUndoRedoOrRollback)
        {
            if (!string.IsNullOrEmpty(newValue))
            {
                element.Label = ComputeSummary(newValue, element.Condition, element.Action);
            }
        }
        base.OnValueChanging(element, oldValue, newValue);
    }
}

三、軟性約束:Validation (驗證) 機制

與規則被動觸發不同,驗證屬於主動觸發:提供右鍵選單、開啟/儲存模型時自動執行,允許使用者暫時違反但給予警告,不阻擋儲存。適用於「最好遵守但不強制」的商業規則。

需驗證的規則

  1. State.Name 不可為空,且需符合 C# 識別碼命名規則。
  2. 初始狀態不可作為 Transition 目標;結束狀態不可作為 Transition 來源。
  3. 每個 StateMachine 至少要有一個初始狀態。

實作步驟

1. 建立驗證類別架構

在 CustomCode 資料夾下新增 Validation 子資料夾存放驗證類別。

2. State 層級驗證

[ValidationState(ValidationState.Enabled)]
public partial class State
{
    [ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
    private void ValidateAttributeNameAsValidIdentifier(ValidationContext context)
    {
        var csharp = new Microsoft.CSharp.CSharpCodeProvider();
        if (string.IsNullOrEmpty(this.Name.Trim()))
            context.LogError("State 的名稱不能為空", "StateMachine – State - 01", this);
        else if (!csharp.IsValidIdentifier(Name))
            context.LogError("State 的名稱不合法", "StateMachines – State - 02", this);
    }

    // 初始/結束狀態不得作為 Transition 來源/目標的驗證同理可加入
}

3. StateMachine 層級驗證 (至少一個初始狀態)

[ValidationState(ValidationState.Enabled)]
public partial class StateMachine
{
    [ValidationMethod(ValidationCategories.Open | ValidationCategories.Save | ValidationCategories.Menu)]
    private void ValidateStateMachineHasOneInitialState(ValidationContext context)
    {
        if (!States.Exists(p => p.Kind == StateKind.Initial))
            context.LogError("狀態機至少應該有一個初始狀態", "StateMachine - 01", this);
    }
}

4. 啟用驗證功能

開啟 DslDefinition.dsl,在 DSL Explorer 中選取 Editor / Validation,將 Use Menu、Use Open、Use Save 全設為 True。

啟用驗證選項

5. 測試驗證

重新轉換所有範本,建置並啟動實驗專案。右鍵設計介面選擇「全部驗證」:

驗證錯誤輸出視窗

四、將「結束狀態不可為 Transition 來源」升級為硬性約束

此規則屬業務邏輯核心,不應允許使用者違反。改用 Connection Builder 自訂接受 機制在拖曳建立連線時直接阻擋。

步驟

  1. DSL Explorer:Connection Builder / TransitionBuilder / Link Connect Directives / Transition。
  2. 在 DSL Details 視窗將來源角色 State 設為 自訂接受 (Custom Accept)。
    設定自訂接受
  3. 轉換所有範本、重建方案——編譯錯誤提示需實作 TransitionBuilder 兩個靜態方法。
  4. 在 CustomCode 新增 TransitionBuilder 靜態部分類別:
namespace Company.LanguageSm
{
    public static partial class TransitionBuilder
    {
        private static bool CanAcceptStateAsSource(State state)
        {
            return (state != null) && (state.Kind != StateKind.Final);
        }
        private static bool CanAcceptStateAndStateAsSourceAndTarget(State sourceState, State targetState)
        {
            return CanAcceptStateAsSource(sourceState);
        }
    }
}
  1. 再次執行實驗專案,拖曳 Transition 從結束狀態出發時,滑鼠游標顯示禁止圖示,無法建立連線。

五、總結

  • Rule (硬性約束):交易中被動觸發,適合資料完整性、屬性聯動等「不可違反」規則。
  • Validation (軟性約束):主動觸發 (選單/開啟/儲存),適合命名規範、最佳實務等「建議遵守」規則,提供彈性。
  • Connection Builder Custom Accept:在模型編輯器層面直接阻擋非法連線建立,使用者體驗最佳。
  • 優秀 DSL 設計器應硬軟結合:核心業務規則用硬性約束 (Rule/Connection Builder),輔助規範用軟性驗證。

程式碼下載

LanguageSm4.rar

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved