更新:
再次感谢你的例子,它们对我很有帮助,我并不是说
夺走他们的一切。
Aren't the currently given examples, as far as I understand them & state-machines, only half of what we usually understand by a state-machine?
In the sense that the examples do change state but that's only represented by changing the value of a variable (and allowing different value- changes in different states), while usually, a state machine should also change its behavior, and behavior not (only) in the sense of allowing different value changes for a variable depending on the state, but in the sense of allowing different methods to be executed for different states.
还是我对状态机及其常用用法有误解?
最初的问题:
我发现了关于c#中的状态机和迭代器块的讨论,以及用于创建状态机和c#的工具,所以我发现了很多抽象的东西,但作为一个新手,所有这些都有点令人困惑。
因此,如果有人能提供一个c#源代码-示例,实现一个简单的状态机,可能只有3,4个状态,那就太好了,只是为了了解它的要点。
其他替代在此回购https://github.com/lingkodsoft/StateBliss
使用流畅的语法,支持触发器。
public class BasicTests
{
[Fact]
public void Tests()
{
// Arrange
StateMachineManager.Register(new [] { typeof(BasicTests).Assembly }); //Register at bootstrap of your application, i.e. Startup
var currentState = AuthenticationState.Unauthenticated;
var nextState = AuthenticationState.Authenticated;
var data = new Dictionary<string, object>();
// Act
var changeInfo = StateMachineManager.Trigger(currentState, nextState, data);
// Assert
Assert.True(changeInfo.StateChangedSucceeded);
Assert.Equal("ChangingHandler1", changeInfo.Data["key1"]);
Assert.Equal("ChangingHandler2", changeInfo.Data["key2"]);
}
//this class gets regitered automatically by calling StateMachineManager.Register
public class AuthenticationStateDefinition : StateDefinition<AuthenticationState>
{
public override void Define(IStateFromBuilder<AuthenticationState> builder)
{
builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
.Changing(this, a => a.ChangingHandler1)
.Changed(this, a => a.ChangedHandler1);
builder.OnEntering(AuthenticationState.Authenticated, this, a => a.OnEnteringHandler1);
builder.OnEntered(AuthenticationState.Authenticated, this, a => a.OnEnteredHandler1);
builder.OnExiting(AuthenticationState.Unauthenticated, this, a => a.OnExitingHandler1);
builder.OnExited(AuthenticationState.Authenticated, this, a => a.OnExitedHandler1);
builder.OnEditing(AuthenticationState.Authenticated, this, a => a.OnEditingHandler1);
builder.OnEdited(AuthenticationState.Authenticated, this, a => a.OnEditedHandler1);
builder.ThrowExceptionWhenDiscontinued = true;
}
private void ChangingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
{
var data = changeinfo.DataAs<Dictionary<string, object>>();
data["key1"] = "ChangingHandler1";
}
private void OnEnteringHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
{
// changeinfo.Continue = false; //this will prevent changing the state
}
private void OnEditedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
{
}
private void OnExitedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
{
}
private void OnEnteredHandler1(StateChangeInfo<AuthenticationState> changeinfo)
{
}
private void OnEditingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
{
}
private void OnExitingHandler1(StateChangeGuardInfo<AuthenticationState> changeinfo)
{
}
private void ChangedHandler1(StateChangeInfo<AuthenticationState> changeinfo)
{
}
}
public class AnotherAuthenticationStateDefinition : StateDefinition<AuthenticationState>
{
public override void Define(IStateFromBuilder<AuthenticationState> builder)
{
builder.From(AuthenticationState.Unauthenticated).To(AuthenticationState.Authenticated)
.Changing(this, a => a.ChangingHandler2);
}
private void ChangingHandler2(StateChangeGuardInfo<AuthenticationState> changeinfo)
{
var data = changeinfo.DataAs<Dictionary<string, object>>();
data["key2"] = "ChangingHandler2";
}
}
}
public enum AuthenticationState
{
Unauthenticated,
Authenticated
}
}
下面是一个非常经典的有限状态机的例子,它模拟了一个非常简化的电子设备(比如电视)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace fsm
{
class Program
{
static void Main(string[] args)
{
var fsm = new FiniteStateMachine();
Console.WriteLine(fsm.State);
fsm.ProcessEvent(FiniteStateMachine.Events.PlugIn);
Console.WriteLine(fsm.State);
fsm.ProcessEvent(FiniteStateMachine.Events.TurnOn);
Console.WriteLine(fsm.State);
fsm.ProcessEvent(FiniteStateMachine.Events.TurnOff);
Console.WriteLine(fsm.State);
fsm.ProcessEvent(FiniteStateMachine.Events.TurnOn);
Console.WriteLine(fsm.State);
fsm.ProcessEvent(FiniteStateMachine.Events.RemovePower);
Console.WriteLine(fsm.State);
Console.ReadKey();
}
class FiniteStateMachine
{
public enum States { Start, Standby, On };
public States State { get; set; }
public enum Events { PlugIn, TurnOn, TurnOff, RemovePower };
private Action[,] fsm;
public FiniteStateMachine()
{
this.fsm = new Action[3, 4] {
//PlugIn, TurnOn, TurnOff, RemovePower
{this.PowerOn, null, null, null}, //start
{null, this.StandbyWhenOff, null, this.PowerOff}, //standby
{null, null, this.StandbyWhenOn, this.PowerOff} }; //on
}
public void ProcessEvent(Events theEvent)
{
this.fsm[(int)this.State, (int)theEvent].Invoke();
}
private void PowerOn() { this.State = States.Standby; }
private void PowerOff() { this.State = States.Start; }
private void StandbyWhenOn() { this.State = States.Standby; }
private void StandbyWhenOff() { this.State = States.On; }
}
}
}
我推荐state.cs。我个人使用state.js (JavaScript版本),并且非常满意。c#版本以类似的方式工作。
你实例化状态:
// create the state machine
var player = new StateMachine<State>( "player" );
// create some states
var initial = player.CreatePseudoState( "initial", PseudoStateKind.Initial );
var operational = player.CreateCompositeState( "operational" );
...
你实例化了一些转换:
var t0 = player.CreateTransition( initial, operational );
player.CreateTransition( history, stopped );
player.CreateTransition<String>( stopped, running, ( state, command ) => command.Equals( "play" ) );
player.CreateTransition<String>( active, stopped, ( state, command ) => command.Equals( "stop" ) );
在状态和转场上定义动作:
t0.Effect += DisengageHead;
t0.Effect += StopMotor;
差不多就是这样了。更多信息请查看网站。
不确定我是否错过了重点,但我认为这里没有一个答案是“简单的”状态机。我通常所说的简单状态机是使用一个内部有开关的循环。这就是我们在PLC /微芯片编程或C/ c++编程中使用的方法。
优点:
容易写。不需要特殊的物品和东西。你甚至不需要面向对象。
当它很小的时候,很容易理解。
缺点:
当有很多状态时,可能会变得相当大,很难阅读。
它是这样的:
public enum State
{
First,
Second,
Third,
}
static void Main(string[] args)
{
var state = State.First;
// x and i are just examples for stuff that you could change inside the state and use for state transitions
var x = 0;
var i = 0;
// does not have to be a while loop. you could loop over the characters of a string too
while (true)
{
switch (state)
{
case State.First:
// Do sth here
if (x == 2)
state = State.Second;
// you may or may not add a break; right after setting the next state
// or do sth here
if (i == 3)
state = State.Third;
// or here
break;
case State.Second:
// Do sth here
if (x == 10)
state = State.First;
// or do sth here
break;
case State.Third:
// Do sth here
if (x == 10)
state = State.First;
// or do sth here
break;
default:
// you may wanna throw an exception here.
break;
}
}
}
如果它真的应该是一个状态机,你调用的方法会根据你所处的状态做出不同的反应:状态设计模式是更好的方法