Ich habe kürzlich über die boost::statechart
Bibliothek (Finite State Machines) gelesen und das Konzept geliebt.
Hat C # einen ähnlichen Mechanismus? Oder kann es mithilfe eines bestimmten Entwurfsmusters implementiert werden?
Ja, C # hat Iteratorblöcke , die vom Compiler generierte Zustandsmaschinen sind.
Wenn Sie eine eigene Zustandsmaschine implementieren möchten, können Sie benutzerdefinierte Implementierungen der IEnumerable<T>
- und IEnumerator<T>
-Schnittstellen erstellen.
Bei beiden Ansätzen wird die Implementierung des iterator-Musters durch .NET Framework hervorgehoben.
.NET 4 Update 1 unterstützt es jetzt in der folgenden Klasse: System.Activities.Statements.StateMachine
Hier ist ein Tutorial, wie man es benutzt . Hier ist ein hands on lab .
Workflow Foundation (.NET 3.0) hat einen Zustandsmaschinen-Workflow. 4.0 hat derzeit nicht genau dasselbe, aber Sie können auf jeden Fall einen Zustandsmaschinen-Workflow mit 4.0 erstellen.
Ich betreue ein Open-Source-Projekt, das unter anderem eine generische Finite-State-Maschine für .NET implementiert. Es ist auf QuickGraph aufgebaut, so dass Sie viele Algorithmen zur Graphanalyse kostenlos erhalten.
Siehe diese Seite für weitere Informationen zum Projekt und insbesondere " Jolt.Automata: Finite State Machines " für weitere Informationen zu der Funktion.
Überprüfen Sie Stateless -> http://code.google.com/p/stateless/ . Es ist eine leichte Alternative zum schwereren WWF.
Hier sind ein paar Artikel des Autors des Tools:
Zustandsmaschinen in Domänenmodellen
Parametrisierte Auslöser und Wiedereintrittsstaaten in Staatenlosen
Die Dinge, die FSMs in der Nähe sind, sind Workflows in .NET 3.5, Workflows sind jedoch nicht genau FSMs.
Die Verwendung von FSMs besteht darin, dass Sie sie explizit in Ihrem Code erstellen können, wodurch sie weniger Fehler verursachen. Außerdem sind einige Systeme von Natur aus FSMs, daher ist es natürlicher, sie so zu codieren.
Windows Workflow Foundation (WF), das Teil der Basisklassenbibliothek in 3.0 und 3.5 ist, enthält einen Workflowentwurf für Statusmaschinen zum Verwalten von Statusmaschinen für Ihre Anwendungen.
Sie haben den Workflow für die kommende Version 4.0 komplett neu geschrieben, und die neuen Klassen WF 4.0 unterstützen keine Zustandsmaschinen nativ, jedoch werden alle Klassen 3.0/3.5 unter 4.0 weiterhin vollständig unterstützt.
Andere Alternative in diesem Repo https://github.com/lingkodsoft/StateBliss verwendete fließende Syntax, unterstützt Trigger.
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
}
}