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

Windows Workflow Foundation 開發指南:建立自訂活動擴展工作流邊界

     編輯:關於.NET

自訂活動是 Windows Workflow Foundation (WF) 實現領域邏輯封裝與重用的核心。本文基於 .NET Framework 3.0,系統闡述基本活動與複合活動的建構要點、非同步/事件驅動活動模式、設計時體驗客製化、以及驗證與錯誤處理機制,並以 CreateUserActivity (基本) 與 SwitchActivity (複合) 為實例贯穿始終。

一、基本活動:封裝單一職責邏輯

1. 核心實作:覆寫 Execute 方法

protected override ActivityExecutionStatus Execute(ActivityExecutionContext context) {
    var provider = String.IsNullOrEmpty(MembershipProviderName) 
        ? Membership.Provider 
        : Membership.Providers[MembershipProviderName];
    MembershipCreateStatus status;
    provider.CreateUser(UserName, Password, Email, null, null, true, Guid.NewGuid(), out status);
    return ActivityExecutionStatus.Closed; // 宣告完成
}

基本活動執行完畢即回傳 Closed,讓運行時排程下一個活動。

2. 相依屬性:啟用活動繫結與設計時體驗

相依屬性 (DependencyProperty) 儲存於 DependencyObject 字典,支援:

  • 活動繫結:屬性值自動在活動間流動 (如工作流屬性 → 活動屬性)。
  • 屬性提升:複合活動將子活動屬性提升為自身屬性。
  • 變更通知:監聽屬性變更觸發邏輯。
  • 狀態序列化:統一儲存便於持久化。
public static DependencyProperty UserNameProperty = DependencyProperty.Register(
    "UserName", typeof(string), typeof(CreateUserActivity));

[Description("此使用者的新使用者名稱")]
[Category("User")]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public string UserName {
    get { return (string)base.GetValue(UserNameProperty); }
    set { base.SetValue(UserNameProperty, value); }
}
原則:凡可能透過繫結受益的屬性,**一律使用相依屬性**。

二、複合活動:組合子活動實現控制流

1. 繼承 SequenceActivity:聲明式組合 (設計器支援)

  • 新增活動專案 → 選擇「工作流活動」 → 基類設為 SequenceActivity。
  • 設計器拖曳子活動 (IfElse、SendEmail、CreateUser 等) 定義流程。
  • 右鍵子活動 →「提升可繫結屬性」→ 自動在複合活動宣告相依屬性並繫結。
  • 優點:零程式碼控制流,完整設計器體驗。

2. 繼承 CompositeActivity:命令式控制子活動排程 (如 SwitchActivity)

SwitchActivity 模擬 C# switch:多個 SwitchBranchActivity (繼承 SequenceActivity + Condition 屬性),僅執行條件為 true 的分支。

核心 Execute 邏輯

protected override ActivityExecutionStatus Execute(ActivityExecutionContext context) {
    foreach (Activity child in EnabledActivities) {
        var branch = child as SwitchBranchActivity;
        if (branch != null && branch.Condition.Evaluate(branch, context)) {
            branch.Closed += OnChildClosed;          // 註冊完成通知
            context.ExecuteActivity(branch);         // 排程執行
        }
    }
    return ActivityExecutionStatus.Executing;      // 尚未完成,等待子活動
}

完成通知與關閉

void OnChildClosed(object sender, ActivityExecutionStatusChangedEventArgs e) {
    var branch = sender as SwitchBranchActivity;
    branch.Closed -= OnChildClosed;
    // 檢查是否還有其他分支需執行 (Switch 僅執行一個,故直接關閉)
    context.CloseActivity();
}

關鍵點:回傳 Executing 讓運行時暫停父流程;透過 IActivityEventListener 監聽子活動 Closed 事件;所有分支完成後呼叫 context.CloseActivity() 相當於回傳 Closed。

三、非同步與事件驅動活動

WF 運行時會閒置持久化工作流,**活動不可直接掛載外部事件處理常式** (持久化後會遺失)。解決方案:工作流佇列機制。

模式:佇列 + IActivityEventListener + 本地服務

  1. 活動 Execute 中建立/取得佇列 (WorkflowQueuingService),註冊 QueueItemAvailable 事件。
  2. 回傳 Executing 等待外部觸發。
  3. 本地服務 (宿主註冊的類別) 長期持有事件處理常式 (如 FileSystemWatcher、WMI 事件),事件觸發時將資料入佇列 (Enqueue)。
  4. 活動 OnEvent 取出資料處理,呼叫 context.CloseActivity() 結束。

介面契約

  • IEventActivity:定義 Subscribe/Unsubscribe/QueueName,供運行時管理訂閱週期。
  • IActivityEventListener<QueueEventArgs>:處理佇列項目可用通知。
範例:ReadLineActivity (主控台輸入)、FileWatcherActivity (SDK 內建) 均採此模式。

四、錯誤處理

  • 活動邏輯拋出例外 → 運行時呼叫 HandleFault → 預設行為呼叫 Cancel 釋放資源。
  • 覆寫 HandleFault 可執行特定清理 (釋放非受控資源、取消非同步操作)。
  • 複合活動支援 FaultHandlers:子活動錯誤後執行的補償邏輯 (設計器視圖配置)。
  • 區分:Cancel 為主動式前向執行語義 (如 Parallel 取消其他分支);Fault 為被動式異常處理,兩者語義不同,勿混淆。

五、設計時體驗客製化

1. 活動設計器 (ActivityDesigner)

  • 關聯:[Designer(typeof(MyDesigner), typeof(IDesigner))]。
  • 核心功能:
    • 外觀:繼承 ActivityDesignerTheme 設定漸層色、前景色、圖示 (ToolboxBitmap)。
    • 互動:覆寫 Verbs 加入右鍵選單命令 (如「清除所有條件」)。
    • 驗證 UI:覆寫 DesignerVerbs (錯誤選單)、SmartTagVerbs (智慧標籤)。
    • 結構化佈局:複合活動設計器繼承 ParallelActivityDesigner (分支佈局) 或 FreeFormActivityDesigner (自由佈局)。
    • 封裝呈現:若不想暴露內部子活動,改繼承 ActivityDesigner 僅繪製單一圖塊。

2. 設計器驗證邏輯

  • CanBeParentedTo:限制父活動類型 (如 SwitchBranch 僅允許在 Switch 下)。
  • CanInsertActivities:限制可加入的子活動類型。
  • 僅在設計器環境生效,程式碼建構不受限。

3. 自訂驗證器 (ActivityValidator)

編譯期與設計期皆執行,不受設計器限制。

public override ValidationErrorCollection Validate(ValidationManager manager, object obj) {
    var errors = base.Validate(manager, obj);
    var act = obj as CreateUserActivity;
    if (act != null && act.Parent != null && !act.IsBindingSet(CreateUserActivity.PasswordProperty)) {
        errors.Add(new ValidationError("密碼必須使用活動繫結設定", 1, false, "Password"));
    }
    return errors;
}
關聯:[ActivityValidator(typeof(CreateUserValidator))] 標記於活動類別。

結語

WF 提供與內建活動同等的擴展點:從執行語義、設計器體驗、驗證規則到錯誤處理,開發者擁有完整控制權。建構健壯的活動庫,能將領域邏輯無縫整合進 WF 處理模型,充分發揮視覺化流程開發的價值。善用社群 (wf.netfx3.com) 分享與發現活動元件。

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