在 C# 或 VB.NET 中使用 'System.Activities.Statements.StateMachine' class 的示例

Example to use 'System.Activities.Statements.StateMachine' class in C# or VB.NET

我觉得有必要要求 System.Activities.Statements.StateMachine class 的完整示例用法来存储和恢复 Control 实例的状态(这意味着,我会喜欢存储控件的状态以替换基于控件属性和 "commands") 的典型 undo/redo 方法。

我一直在 Google 上搜索自制的状态机实现,我找到了很多,但后来我在 .NET Framework Class 库中发现了 Microsoft 的这个实现(那么现在我没有理由依赖任何自制的实现来重新发明轮子),但是,MSDN 没有代码示例来介绍 class 的用法,我没有找到任何结果在 Google 上演示了它的用法(以及我在 MSDN 上看到的一些其他相关成员的小代码示例,我根本不明白我应该如何使用它们)。

然后现在我真的是瞎了,试图通过反复试验来学习如何使用 class 及其相关成员。

下面是我目前尝试的方法,我坚持 "register" obj 变量状态的意图,具体是 System.Activities.OutArgument.Set and System.Activities.OutArgument.Get methods that takes a ActivityContext 作为第一个参数而且我不知道我应该传递给他们什么值(在我下面的代码中,对这些方法的调用会引发异常,因为该值不能是 null)。

C#(由在线代码翻译器翻译,可能有语法错误):

using System.Activities;
using System.Activities.Statements;

// Create a container for statemachines
StateMachine sm = new StateMachine();

// Declare an object to test its state...
string obj = null;

// Modify the state of 'obj'.
obj = "hello";

// Save 1st state of 'obj'.
Activity<string> act1 = obj;
act1.Result = new OutArgument<string>();
act1.Result.Set(null, obj);
State state1 = new State();
state1.Entry = act1;

// Modify the state of 'obj'.
obj = "hello world";

// Save 2nd state of 'obj'.
Activity<string> act2 = obj;
act2.Result = new OutArgument<string>();
act2.Result.Set(null, obj);
State state2 = new State();
state2.Entry = act2;

// Add saved states into the statemachine collection.
sm.States.Add(state1);
sm.States.Add(state2);

// Modify the state of 'obj'.
obj = string.Empty;

// Restore last saved state of 'obj'.
obj = ((Activity<string>)sm.States.Last().Entry).Result.Get(null);

VB.NET:

Imports System.Activities
Imports System.Activities.Statements

' Create a container for statemachines
Dim sm As New StateMachine()

' Declare an object to test its state...
Dim obj As String

' Modify the state of 'obj'.
obj = "hello"

' Save 1st state of 'obj'.
Dim act1 As Activity(Of String) = obj
act1.Result = New OutArgument(Of String)
act1.Result.Set(Nothing, obj)
Dim state1 As New State()
state1.Entry = act1

' Modify the state of 'obj'.
obj = "hello world"

' Save 2nd state of 'obj'.
Dim act2 As Activity(Of String) = obj
act2.Result = New OutArgument(Of String)
act2.Result.Set(Nothing, obj)
Dim state2 As New State()
state2.Entry = act2

' Add saved states into the statemachine collection.
sm.States.Add(state1)
sm.States.Add(state2)

' Modify the state of 'obj'.
obj = String.Empty

' Restore last saved state of 'obj'.
obj = DirectCast(sm.States.Last().Entry, Activity(Of String)).Result.Get(Nothing)

...还有一些说明,例如 Activity<string> act1 = obj; / Dim act1 As Activity(Of String) = obj 我不确定这样做是否正确。

PS:请注意,在上面的代码中,我使用了一个 String 变量只是为了简化事情,但我需要保存和恢复 Control 的状态,正如我之前解释的那样。

例如 System.Activities 命名空间属于 Windows Workflow Foundation. Activity classes in this namespace are used to build workflows, like SharePoint workflows

StateMachine class 是多个子活动的容器,这些子活动共同构成 State Machine Workflow

定义工作流后,您可以使用 WorkflowInvokerWorkflowApplication 使用工作流引擎 运行 它。来自 docs:

WorkflowInvoker provides a simple way for invoking a workflow as if it were a method call and can be used only for workflows that do not use persistence. WorkflowApplication provides a richer model for executing workflows that includes notification of life-cycle events, execution control, bookmark resumption, and persistence.

您引用的 ActivityContext 包含有关工作流 运行 时间的信息,例如执行 activity 的主机。 运行时间填写信息所以不能自己注入东西

您找不到太多使用 StateMachine class 的示例的原因是大多数工作流程都是使用创建 .XAML 文件的图形设计器构建的,而我不'认为很多都是仅使用代码构建的。

现在,考虑到所有这些,您可以看到,对于您的场景,这不是一个很好的选择,当然也不是为 undo/redo 用例设计的。

有 framework/libraries 可能更合适,比如来自 PostSharp 的 this