Using MutationObserver in GeckoFx with C#? - c#

I am using GeckoFx to perform a login to a specific website. This website edits the page with new information should the login fail (or require additional authentication, such as a ReCaptcha). Unfortunately, it is vital that I have access an event when the page is updated. I have tried numerous approaches mainly
A continual check if the uri is still the same upon each login attempt and a subsequent check on the specific element in question (to see if the display: none property was changed. (This resulted in an infinite loop as it seems GeckoFx updates the page in a nonblocking way, causing the program to go into an infinite loop)
Sleeping for ~5 seconds between login requests and using the aforementioned uri check. All this did (predictably, I was grasping at straws) was freeze the browser for 5 seconds and still fail to update the page
Searching the GeckoFx codebase for a specific event when the page is updated similar to the DocumentCompleted event (no such luck).
The most common approach I have read about (and one that makes the most sense) is to use a MutationObserver. It seems that all of the answers across the internet involve injecting Javascript in order to perform the requisite task. Seeing as all of my programming background has not touched web development whatsoever, I'm trying to stick to what I know.
Here is my approach so far, unfortunately, it is not much.
public class GeckoTestWebLogin
{
private readonly string _user;
private readonly string _pass;
public GeckoWebBrowser Gweb;
public Uri LoginUri { get; } = new Uri("https://website.com/login/");
public bool LoginCompleted { get; private set; } = false;
public bool Loaded { get; private set; } = false;
public GeckoTestWebLogin(string user, string pass)
{
_user = user;
_pass = pass;
Xpcom.EnableProfileMonitoring = false;
Xpcom.Initialize("Firefox");
//this code is for testing purposes, it will be removed upon project completion
CookieManager.RemoveAll();
Gweb = new GeckoWebBrowser();
Gweb.DocumentCompleted += DocLoaded;
//right about here is where I get lost, where can I set a callback method for the observer to report back to? Is this even how it works?
MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);
}
private void TestObservedEvent(string parms, object[] objs)
{
MessageBox.Show("The page was changed # " + DateTime.Now);
}
public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
{
Loaded = true;
if (Gweb.Url != LoginUri) return;
AttemptLogin();
}
private void AttemptLogin()
{
GeckoElementCollection elements = Gweb.Document.GetElementsByTagName("input");
foreach (GeckoHtmlElement element in elements)
{
switch (element.Id)
{
case "username":
element.SetAttribute("value", _user);
break;
case "password":
element.SetAttribute("value", _pass);
break;
case "importantchangedinfo":
GeckoHtmlElement authcodeModal =
(GeckoHtmlElement)
Gweb.Document.GetElementsByClassName("login_modal").First();
if (authcodeModal.Attributes["style"].NodeValue != "display: none")
{
InputForm form = new InputForm { InputDescription = "Captcha Required!" };
form.ShowDialog();
elements.FirstOrDefault(x => x.Id == "captchabox")?.SetAttribute("value", form.Input);
}
break;
}
}
elements.FirstOrDefault(x => x.Id == "Login")?.Click();
}
public void Login()
{
//this will cause the DocLoaded event to fire after completion
Gweb.Navigate(LoginUri.ToString());
}
}
As stated in the above code in the comments, I am completely lost at
MutationObserver mutationObserver = new MutationObserver(Gweb.Window.DomWindow, (nsISupports)Gweb.Document.DomObject);
I can't seem to find anything in GeckoFx's source for MutationObserver that would allow me to set a callback/event/whathaveyou. Is my approach the correct way to go about things or am I left with no options other than to inject Javascript into the page?
Much appreciated, thank you in advance.
Here is my attempt at option 2 in Tom's answer:
(Added into GeckoTestWebLogin)
public void DocLoaded(object obj, GeckoDocumentCompletedEventArgs e)
{
Loaded = true;
if (Gweb.Url != LoginUri) return;
MutationEventListener mutationListener = new MutationEventListener();
mutationListener.OnDomMutation += TestObservedEvent;
nsIDOMEventTarget target = Xpcom.QueryInterface<nsIDOMEventTarget>(/*Lost here*/);
using (nsAString modified = new nsAString("DOMSubtreeModified"))
target.AddEventListener(modified, mutationListener, true, false, 0);
AttemptLogin();
}
MutationEventListener.cs:
public delegate void OnDomMutation(/*DomMutationArgs args*/);
public class MutationEventListener : nsIDOMEventListener
{
public event OnDomMutation OnDomMutation;
public void HandleEvent(nsIDOMEvent domEvent)
{
OnDomMutation?.Invoke(/*new DomMutationArgs(domEvent, this)*/);
}
}

I don't think Geckofx's webidl compiler is currently advanced enough to generate the callback constructor.
Option 1. - Enhance MutationObserver source.
You could modify MutationObserver source manually to add the necessary constructor callback. Then recompile Geckofx. (I haven't look to see how difficult this is)
Option 2. - Use old style Mutation events.
public class DOMSubtreeModifiedEventListener : nsIDOMEventListener
{
... // Implement HandleEvent
}
Then something like (maybe in DocumentCompleted event handler):
_domSubtreeModifiedEventListener = new DOMSubtreeModifiedEventListener(this);
var target = Xpcom.QueryInterface<nsIDOMEventTarget>(body);
using (nsAString subtreeModified = new nsAString("DOMSubtreeModified"))
target.AddEventListener(subtreeModified, _domSubtreeModifiedEventListener, true, false, 0);
Option 3. - Use Idle + Check.
Add an winforms Application.idle event handler - and examine the document, to know when its ready.
Option 4. - Inject a javascript callback.
(As you have already mentioned) - This example is waiting until after a resize is done.
basically inject: "<body onresize=fireResizedEventAfterDelay()>" : then inject something like this:
string fireResizedEventAfterDelayScript = "<script>\n" +
"var resizeListner;" +
"var msDelay = 20;" +
"function fireResizedEventAfterDelay() {" +
"clearTimeout(resizeListner);" +
"resizeListner = setTimeout(function() { document.dispatchEvent (new MessageEvent('resized')); }, msDelay);" +
"}\n" +
"</script>\n";
Then in the C#:
browser.AddMessageEventListener("resized", (s) => runafterImDone())

Related

StreamInsight pass Window Start Time to UDA

I have a problem I am stuck for two days now. Maybe someone of you guys can help me.
I try to get the starttime of a window passed to a user defined aggregate. Unfortunately I don't know how to do this. The way I thought it should work looks like that:
var tot = from row in tumblingWin
select new
{
value = row.UserDefinedAggregate<Dataclass, Total2, double>(new StartBoundsConfig
{
Winstart = row.WinStart().Ticks
}) * processinginterval,
};
And the UDA looks like this:
public class Total2: CepAggregate<Dataclass,double>
{
private Dataclass lastone; //keep it, if needed for next window
private StartBoundsConfig _conf;
public Total2(StartBoundsConfig config)
{
_conf = config;
}
public override double GenerateOutput(IEnumerable<Dataclass> events)
{
//TODO check if value on window start => if not use last from previous as starting value
bool checkfirst = true;
long result = 0;
long tsone = 0;
foreach (var evts in events)
{
if (checkfirst == true)
{
tsone = evts.Gentime.Ticks;
checkfirst = false;
}
else
{
long tstwo = evts.Gentime.Ticks;
long delta = tstwo - tsone;
long value = (long) evts.Value;
result += delta*value;
tsone = tstwo;
}
lastone = evts;
}
return result;
}
}
I tried to pass the window start to the config of the UDA and read it from there.
Has anyone an idea why this doesn't work that way and how I could get the starttime of the window passed to the UDA to use it for calculation there?
I am very grateful for any hint.
Joe
You need a time-sensitive UDA. Inherit from CepTimeSensitiveAggregate (see http://technet.microsoft.com/en-us/library/ee842915.aspx) and your generate output method will have the WindowDescriptor as a part of the signature. You'll also get, as a bonus, the temporal headers for the events so you won't need to enqueue this information as a part of your payload. While there are some edge use cases that would require this, in most cases, you don't need it.

DotNetNuke ModuleAction server-side processing

In DNN it is possible to add a ModuleAction menu item. According this article on the DNN site it is even possible to do some additional processing on the server-side. After converting the code to C#, the ActionHandler is never called.
This is my code:
public ModuleActionCollection ModuleActions
{
get
{
ModuleActionCollection Actions = new ModuleActionCollection();
ModuleAction urlEventAction = new ModuleAction(ModuleContext.GetNextActionID());
urlEventAction.Title = "Action Event Example";
urlEventAction.CommandName = "redirect";
urlEventAction.CommandArgument = "cancel";
urlEventAction.Url = "http://dotnetnuke.com";
urlEventAction.UseActionEvent = true;
urlEventAction.Secure = DotNetNuke.Security.SecurityAccessLevel.Admin;
Actions.Add(urlEventAction);
return Actions;
}
}
private void MyActions_Click(object sender, DotNetNuke.Entities.Modules.Actions.ActionEventArgs e)
{
DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, string.Format(Localization.GetString("ClickMessage", LocalResourceFile), e.Action.CommandName), ModuleMessage.ModuleMessageType.BlueInfo);
switch (e.Action.CommandName.ToUpper())
{
case "REDIRECT":
if (e.Action.CommandArgument.ToUpper() != "CANCEL")
{
Response.Redirect(e.Action.Url);
}
else
{
DotNetNuke.UI.Skins.Skin.AddModuleMessage(this, "Canceled the Redirect", ModuleMessage.ModuleMessageType.YellowWarning);
}
break;
}
}
And in the page init I attach the event handler:
AddActionHandler(new ActionEventHandler(MyActions_Click));
I also tried attaching in the page load as done by DNN source itself.
The menu item is shown and the redirect to http://dotnetnuke.com is executed.
But my breakpoint in MyActions_Click is never hit.
What am I doing wrong?
I'm running in DotNetNuke 7.1 with module reference to DNN 6.2.
My solution with IPostBackEventHandler instead of the DNN way (until someone corrects me):
public ModuleActionCollection ModuleActions
{
get
{
ModuleActionCollection Actions = new ModuleActionCollection();
Actions.Add(ModuleContext.GetNextActionID(),
"Bla",
"",
"",
"",
"javascript:" + Page.ClientScript.GetPostBackEventReference(this, "ARGUMENT"),
Page.ClientScript.GetPostBackEventReference(this, "ARGUMENT"),
false,
DotNetNuke.Security.SecurityAccessLevel.Edit,
true,
false);
return Actions;
}
}
public void RaisePostBackEvent(String eventArgument)
{
if (eventArgument.ToUpper() == "ARGUMENT")
{
...
Globals.Redirect(HttpContext.Current.Request.RawUrl, false);
}
}
And don't forget to add IPostBackEventHandler to your page class name.
Namespace: using System.Web.UI;
I honestly dont think this is a DNN issue. I would clear down your temp cache and try to debug again.
Leigh

Detect when the selenium webdriver changes url in browser

I need to detect when the url in the browser changes whether it was because of click on a link, a form post or I changed the url in code.
I need it because I'm creating an object to represent the page and I need to dispose recreate it when the url changes.
Here is what I have tried so far:
private string _pageUrl;
protected T _page = default(T);
protected T Page
{
get
{
if (_page == null || UrlHasChanged())
{
_page = GetPage<T>();
SetPageUrl();
}
return _page;
}
}
private bool UrlHasChanged()
{
var driver = Session.GetDriver();
return driver.Url != _pageUrl;
}
public void SetPageUrl()
{
_pageUrl = Session.GetDriver().Url;
}
This works in most cases but it fails when the test goes forward a page and then goes back to the initial page.
I need a way to detect when the url changes so I can reset the _page field.
I'm a Java developer, so, I search in the C# documentation what looked similar to the Java API. I think you should use the EventFiringWebDriver :
EventFiringWebDriver firingDriver = new EventFiringWebDriver(driver);
firingDriver.NavigatingBack += new EventHandler<WebDriverNavigationEventArgs>(...);
firingDriver.NavigatedBack += new EventHandler<WebDriverNavigationEventArgs>(...);
firingDriver.NavigatingForward += new EventHandler<WebDriverNavigationEventArgs>(...);
firingDriver.NavigatedForward += new EventHandler<WebDriverNavigationEventArgs>(...);
I looked at the unit tests and I found this one that may be useful for you :
http://selenium.googlecode.com/svn/trunk/dotnet/test/WebDriver.Support.Tests/Events/EventFiringWebDriverTest.cs

Simple state machine example in C#?

Update:
Again thanks for the examples, they have been very helpful and with the following, I don't mean
to take anything away from them.
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.
Or do I have a misconception of state machines and their common use?
Original question:
I found this discussion about state machines & iterator blocks in c# and tools to create state machines and whatnot for C#, so I found a lot of abstract stuff but as a noob, all of this is a little confusing.
So it would be great if someone could provide a C# source code-example that realizes a simple state machine with perhaps 3,4 states, just to get the gist of it.
Let's start with this simple state diagram:
We have:
4 states (Inactive, Active, Paused, and Exited)
5 types of state transitions (Begin Command, End Command, Pause Command, Resume Command, Exit Command).
You can convert this to C# in a handful of ways, such as performing a switch statement on the current state and command, or looking up transitions in a transition table. For this simple state machine, I prefer a transition table, which is very easy to represent using a Dictionary:
using System;
using System.Collections.Generic;
namespace Juliet
{
public enum ProcessState
{
Inactive,
Active,
Paused,
Terminated
}
public enum Command
{
Begin,
End,
Pause,
Resume,
Exit
}
public class Process
{
class StateTransition
{
readonly ProcessState CurrentState;
readonly Command Command;
public StateTransition(ProcessState currentState, Command command)
{
CurrentState = currentState;
Command = command;
}
public override int GetHashCode()
{
return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();
}
public override bool Equals(object obj)
{
StateTransition other = obj as StateTransition;
return other != null && this.CurrentState == other.CurrentState && this.Command == other.Command;
}
}
Dictionary<StateTransition, ProcessState> transitions;
public ProcessState CurrentState { get; private set; }
public Process()
{
CurrentState = ProcessState.Inactive;
transitions = new Dictionary<StateTransition, ProcessState>
{
{ new StateTransition(ProcessState.Inactive, Command.Exit), ProcessState.Terminated },
{ new StateTransition(ProcessState.Inactive, Command.Begin), ProcessState.Active },
{ new StateTransition(ProcessState.Active, Command.End), ProcessState.Inactive },
{ new StateTransition(ProcessState.Active, Command.Pause), ProcessState.Paused },
{ new StateTransition(ProcessState.Paused, Command.End), ProcessState.Inactive },
{ new StateTransition(ProcessState.Paused, Command.Resume), ProcessState.Active }
};
}
public ProcessState GetNext(Command command)
{
StateTransition transition = new StateTransition(CurrentState, command);
ProcessState nextState;
if (!transitions.TryGetValue(transition, out nextState))
throw new Exception("Invalid transition: " + CurrentState + " -> " + command);
return nextState;
}
public ProcessState MoveNext(Command command)
{
CurrentState = GetNext(command);
return CurrentState;
}
}
public class Program
{
static void Main(string[] args)
{
Process p = new Process();
Console.WriteLine("Current State = " + p.CurrentState);
Console.WriteLine("Command.Begin: Current State = " + p.MoveNext(Command.Begin));
Console.WriteLine("Command.Pause: Current State = " + p.MoveNext(Command.Pause));
Console.WriteLine("Command.End: Current State = " + p.MoveNext(Command.End));
Console.WriteLine("Command.Exit: Current State = " + p.MoveNext(Command.Exit));
Console.ReadLine();
}
}
}
As a matter of personal preference, I like to design my state machines with a GetNext function to return the next state deterministically, and a MoveNext function to mutate the state machine.
You might want to use one of the existing open source Finite State Machines. E.g. bbv.Common.StateMachine found at http://code.google.com/p/bbvcommon/wiki/StateMachine. It has a very intuitive fluent syntax and a lot of features such as, enter/exit actions, transition actions, guards, hierarchical, passive implementation (executed on the thread of the caller) and active implementation (own thread on which the fsm runs, events are added to a queue).
Taking Juliets example the definition for the state machine gets very easy:
var fsm = new PassiveStateMachine<ProcessState, Command>();
fsm.In(ProcessState.Inactive)
.On(Command.Exit).Goto(ProcessState.Terminated).Execute(SomeTransitionAction)
.On(Command.Begin).Goto(ProcessState.Active);
fsm.In(ProcessState.Active)
.ExecuteOnEntry(SomeEntryAction)
.ExecuteOnExit(SomeExitAction)
.On(Command.End).Goto(ProcessState.Inactive)
.On(Command.Pause).Goto(ProcessState.Paused);
fsm.In(ProcessState.Paused)
.On(Command.End).Goto(ProcessState.Inactive).OnlyIf(SomeGuard)
.On(Command.Resume).Goto(ProcessState.Active);
fsm.Initialize(ProcessState.Inactive);
fsm.Start();
fsm.Fire(Command.Begin);
Update: The project location has moved to: https://github.com/appccelerate/statemachine
Here's an example of a very classic finite state machine, modelling a very simplified electronic device (like a TV)
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; }
}
}
}
Some shameless self-promo here, but a while ago I created a library called YieldMachine which allows a limited-complexity state machine to be described in a very clean and simple way. For example, consider a lamp:
Notice that this state machine has 2 triggers and 3 states. In YieldMachine code, we write a single method for all state-related behavior, in which we commit the horrible atrocity of using goto for each state. A trigger becomes a property or field of type Action, decorated with an attribute called Trigger. I've commented the code of the first state and its transitions below; the next states follow the same pattern.
public class Lamp : StateMachine
{
// Triggers (or events, or actions, whatever) that our
// state machine understands.
[Trigger]
public readonly Action PressSwitch;
[Trigger]
public readonly Action GotError;
// Actual state machine logic
protected override IEnumerable WalkStates()
{
off:
Console.WriteLine("off.");
yield return null;
if (Trigger == PressSwitch) goto on;
InvalidTrigger();
on:
Console.WriteLine("*shiiine!*");
yield return null;
if (Trigger == GotError) goto error;
if (Trigger == PressSwitch) goto off;
InvalidTrigger();
error:
Console.WriteLine("-err-");
yield return null;
if (Trigger == PressSwitch) goto off;
InvalidTrigger();
}
}
Short and nice, eh!
This state machine is controlled simply by sending triggers to it:
var sm = new Lamp();
sm.PressSwitch(); //go on
sm.PressSwitch(); //go off
sm.PressSwitch(); //go on
sm.GotError(); //get error
sm.PressSwitch(); //go off
Just to clarify, I've added some comments to the first state to help you understand how to use this.
protected override IEnumerable WalkStates()
{
off: // Each goto label is a state
Console.WriteLine("off."); // State entry actions
yield return null; // This means "Wait until a
// trigger is called"
// Ah, we got triggered!
// perform state exit actions
// (none, in this case)
if (Trigger == PressSwitch) goto on; // Transitions go here:
// depending on the trigger
// that was called, go to
// the right state
InvalidTrigger(); // Throw exception on
// invalid trigger
...
This works because the C# compiler actually created a state machine internally for each method that uses yield return. This construct is usually used to lazily create sequences of data, but in this case we're not actually interested in the returned sequence (which is all nulls anyway), but in the state behaviour that gets created under the hood.
The StateMachine base class does some reflection on construction to assign code to each [Trigger] action, which sets the Trigger member and moves the state machine forward.
But you don't really need to understand the internals to be able to use it.
You can code an iterator block that lets you execute a code block in an orchestrated fashion. How the code block is broken up really doesn't have to correspond to anything, it's just how you want to code it. For example:
IEnumerable<int> CountToTen()
{
System.Console.WriteLine("1");
yield return 0;
System.Console.WriteLine("2");
System.Console.WriteLine("3");
System.Console.WriteLine("4");
yield return 0;
System.Console.WriteLine("5");
System.Console.WriteLine("6");
System.Console.WriteLine("7");
yield return 0;
System.Console.WriteLine("8");
yield return 0;
System.Console.WriteLine("9");
System.Console.WriteLine("10");
}
In this case, when you call CountToTen, nothing actually executes, yet. What you get is effectively a state machine generator, for which you can create a new instance of the state machine. You do this by calling GetEnumerator(). The resulting IEnumerator is effectively a state machine that you can drive by calling MoveNext(...).
Thus, in this example, the first time you call MoveNext(...) you will see "1" written to the console, and the next time you call MoveNext(...) you will see 2, 3, 4, and then 5, 6, 7 and then 8, and then 9, 10. As you can see, it's a useful mechanism for orchestrating how things should occur.
It's useful to remember that state machines are an abstraction, and you don't need particular tools to create one, however tools can be useful.
You can for example realise a state machine with functions:
void Hunt(IList<Gull> gulls)
{
if (gulls.Empty())
return;
var target = gulls.First();
TargetAcquired(target, gulls);
}
void TargetAcquired(Gull target, IList<Gull> gulls)
{
var balloon = new WaterBalloon(weightKg: 20);
this.Cannon.Fire(balloon);
if (balloon.Hit)
{
TargetHit(target, gulls);
}
else
TargetMissed(target, gulls);
}
void TargetHit(Gull target, IList<Gull> gulls)
{
Console.WriteLine("Suck on it {0}!", target.Name);
Hunt(gulls);
}
void TargetMissed(Gull target, IList<Gull> gulls)
{
Console.WriteLine("I'll get ya!");
TargetAcquired(target, gulls);
}
This machine would hunt for gulls and try to hit them with water balloons. If it misses it will try firing one until it hits (could do with some realistic expectations ;)), otherwise it will gloat in the console. It continues to hunt until it's out of gulls to harass.
Each function corresponds to each state; the start and end (or accept) states are not shown. There are probably more states in there than modelled by the functions though. For example after firing the balloon the machine is really in another state than it was before it, but I decided this distinction was impractical to make.
A common way is to use classes to represent states, and then connect them in different ways.
Found this great tutorial online and it helped me wrap my head around finite state machines.
http://gamedevelopment.tutsplus.com/tutorials/finite-state-machines-theory-and-implementation--gamedev-11867
The tutorial is language agnostic, so it can easily be adapted to your C# needs.
Also, the example used (an ant looking for food) is easy to understand.
From the tutorial:
public class FSM {
private var activeState :Function; // points to the currently active state function
public function FSM() {
}
public function setState(state :Function) :void {
activeState = state;
}
public function update() :void {
if (activeState != null) {
activeState();
}
}
}
public class Ant
{
public var position :Vector3D;
public var velocity :Vector3D;
public var brain :FSM;
public function Ant(posX :Number, posY :Number) {
position = new Vector3D(posX, posY);
velocity = new Vector3D( -1, -1);
brain = new FSM();
// Tell the brain to start looking for the leaf.
brain.setState(findLeaf);
}
/**
* The "findLeaf" state.
* It makes the ant move towards the leaf.
*/
public function findLeaf() :void {
// Move the ant towards the leaf.
velocity = new Vector3D(Game.instance.leaf.x - position.x, Game.instance.leaf.y - position.y);
if (distance(Game.instance.leaf, this) <= 10) {
// The ant is extremelly close to the leaf, it's time
// to go home.
brain.setState(goHome);
}
if (distance(Game.mouse, this) <= MOUSE_THREAT_RADIUS) {
// Mouse cursor is threatening us. Let's run away!
// It will make the brain start calling runAway() from
// now on.
brain.setState(runAway);
}
}
/**
* The "goHome" state.
* It makes the ant move towards its home.
*/
public function goHome() :void {
// Move the ant towards home
velocity = new Vector3D(Game.instance.home.x - position.x, Game.instance.home.y - position.y);
if (distance(Game.instance.home, this) <= 10) {
// The ant is home, let's find the leaf again.
brain.setState(findLeaf);
}
}
/**
* The "runAway" state.
* It makes the ant run away from the mouse cursor.
*/
public function runAway() :void {
// Move the ant away from the mouse cursor
velocity = new Vector3D(position.x - Game.mouse.x, position.y - Game.mouse.y);
// Is the mouse cursor still close?
if (distance(Game.mouse, this) > MOUSE_THREAT_RADIUS) {
// No, the mouse cursor has gone away. Let's go back looking for the leaf.
brain.setState(findLeaf);
}
}
public function update():void {
// Update the FSM controlling the "brain". It will invoke the currently
// active state function: findLeaf(), goHome() or runAway().
brain.update();
// Apply the velocity vector to the position, making the ant move.
moveBasedOnVelocity();
}
(...)
}
I'm posting another answer here as this is state machines from a different perspective; very visual.
My original answer is classic imperative code. I think its quite visual as code goes because of the array which makes visualizing the state machine simple. The downside is you have to write all this. Remos's answer alleviates the effort of writing the boiler-plate code but is far less visual. There is the third alternative; really drawing the state machine.
If you are using .NET and can target version 4 of the run time then you have the option of using workflow's state machine activities. These in essence let you draw the state machine (much as in Juliet's diagram) and have the WF run-time execute it for you.
See the MSDN article Building State Machines with Windows Workflow Foundation for more details, and this CodePlex site for the latest version.
That's the option I would always prefer when targeting .NET because its easy to see, change and explain to non programmers; pictures are worth a thousand words as they say!
I haven't tried implementing a FSM in C# yet, but these all sound (or look) very complicated to the way I handled FSM's in the past in low-level languages like C or ASM.
I believe the method I've always known is called something like an "Iterative Loop". In it, you essentially have a 'while' loop that periodically exits based on events (interrupts), then returns to the main loop again.
Within the interrupt handlers, you would pass a CurrentState and return a NextState, which then overwrites the CurrentState variable in the main loop. You do this ad infinitum until the program closes (or the microcontroller resets).
What I'm seeing other answers all look very complicated compared with how a FSM is, in my mind, intended to be implemented; its beauty lies in its simplicity and FSM can be very complicated with many, many states and transitions, but they allow complicated process to be easily broken down and digested.
I realize my response shouldn't include another question, but I am forced to ask: why do these other proposed solutions appear to be so complicated?
They seem to be akin to hitting a small nail with a giant sledge hammer.
Today i deep in State Design Pattern.
I did and tested ThreadState, which equal (+/-) to Threading in C#, as described in picture from Threading in C#
You can easly add new states, configure moves from one state to other is very easy becouse it incapsulated in state implementation
Implementation and using at: Implements .NET ThreadState by State Design Pattern
I made this generic state machine out of Juliet's code. It's working awesome for me.
These are the benefits:
you can create new state machine in code with two enums TState and TCommand,
added struct TransitionResult<TState> to have more control over the output results of [Try]GetNext() methods
exposing nested class StateTransition only through AddTransition(TState, TCommand, TState) making it easier to work with it
Code:
public class StateMachine<TState, TCommand>
where TState : struct, IConvertible, IComparable
where TCommand : struct, IConvertible, IComparable
{
protected class StateTransition<TS, TC>
where TS : struct, IConvertible, IComparable
where TC : struct, IConvertible, IComparable
{
readonly TS CurrentState;
readonly TC Command;
public StateTransition(TS currentState, TC command)
{
if (!typeof(TS).IsEnum || !typeof(TC).IsEnum)
{
throw new ArgumentException("TS,TC must be an enumerated type");
}
CurrentState = currentState;
Command = command;
}
public override int GetHashCode()
{
return 17 + 31 * CurrentState.GetHashCode() + 31 * Command.GetHashCode();
}
public override bool Equals(object obj)
{
StateTransition<TS, TC> other = obj as StateTransition<TS, TC>;
return other != null
&& this.CurrentState.CompareTo(other.CurrentState) == 0
&& this.Command.CompareTo(other.Command) == 0;
}
}
private Dictionary<StateTransition<TState, TCommand>, TState> transitions;
public TState CurrentState { get; private set; }
protected StateMachine(TState initialState)
{
if (!typeof(TState).IsEnum || !typeof(TCommand).IsEnum)
{
throw new ArgumentException("TState,TCommand must be an enumerated type");
}
CurrentState = initialState;
transitions = new Dictionary<StateTransition<TState, TCommand>, TState>();
}
/// <summary>
/// Defines a new transition inside this state machine
/// </summary>
/// <param name="start">source state</param>
/// <param name="command">transition condition</param>
/// <param name="end">destination state</param>
protected void AddTransition(TState start, TCommand command, TState end)
{
transitions.Add(new StateTransition<TState, TCommand>(start, command), end);
}
public TransitionResult<TState> TryGetNext(TCommand command)
{
StateTransition<TState, TCommand> transition = new StateTransition<TState, TCommand>(CurrentState, command);
TState nextState;
if (transitions.TryGetValue(transition, out nextState))
return new TransitionResult<TState>(nextState, true);
else
return new TransitionResult<TState>(CurrentState, false);
}
public TransitionResult<TState> MoveNext(TCommand command)
{
var result = TryGetNext(command);
if(result.IsValid)
{
//changes state
CurrentState = result.NewState;
}
return result;
}
}
This is the return type of TryGetNext method:
public struct TransitionResult<TState>
{
public TransitionResult(TState newState, bool isValid)
{
NewState = newState;
IsValid = isValid;
}
public TState NewState;
public bool IsValid;
}
How to use:
This is how you can create a OnlineDiscountStateMachine from the generic class:
Define an enum OnlineDiscountState for its states and an enum OnlineDiscountCommand for its commands.
Define a class OnlineDiscountStateMachine derived from the generic class using those two enums
Derive the constructor from base(OnlineDiscountState.InitialState) so that the initial state is set to OnlineDiscountState.InitialState
Use AddTransition as many times as needed
public class OnlineDiscountStateMachine : StateMachine<OnlineDiscountState, OnlineDiscountCommand>
{
public OnlineDiscountStateMachine() : base(OnlineDiscountState.Disconnected)
{
AddTransition(OnlineDiscountState.Disconnected, OnlineDiscountCommand.Connect, OnlineDiscountState.Connected);
AddTransition(OnlineDiscountState.Disconnected, OnlineDiscountCommand.Connect, OnlineDiscountState.Error_AuthenticationError);
AddTransition(OnlineDiscountState.Connected, OnlineDiscountCommand.Submit, OnlineDiscountState.WaitingForResponse);
AddTransition(OnlineDiscountState.WaitingForResponse, OnlineDiscountCommand.DataReceived, OnlineDiscountState.Disconnected);
}
}
use the derived state machine
odsm = new OnlineDiscountStateMachine();
public void Connect()
{
var result = odsm.TryGetNext(OnlineDiscountCommand.Connect);
//is result valid?
if (!result.IsValid)
//if this happens you need to add transitions to the state machine
//in this case result.NewState is the same as before
Console.WriteLine("cannot navigate from this state using OnlineDiscountCommand.Connect");
//the transition was successfull
//show messages for new states
else if(result.NewState == OnlineDiscountState.Error_AuthenticationError)
Console.WriteLine("invalid user/pass");
else if(result.NewState == OnlineDiscountState.Connected)
Console.WriteLine("Connected");
else
Console.WriteLine("not implemented transition result for " + result.NewState);
}
Not sure whether I miss the point, but I think none of the answers here are "simple" state machines. What i usually call a simple state machine is using a loop with a switch inside. That is what we used in PLC / microchip programming or in C/C++ programming at the university.
advantages:
easy to write. no special objects and stuff required. you dont even need object orientation for it.
when it is small, it is easy to understand.
disadvantages:
can become quite big and hard to read, when there are many states.
It looked like that:
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;
}
}
}
if it should be really a state machine on which you call methods which react depending on which state you are in differently: state design pattern is the better approach
In my opinion a state machine is not only meant for changing states but also (very important) for handling triggers/events within a specific state. If you want to understand state machine design pattern better, a good description can be found within the book Head First Design Patterns, page 320.
It is not only about the states within variables but also about handling triggers within the different states. Great chapter (and no, there is no fee for me in mentioning this :-) which contains just an easy to understand explanation.
What a bout StatePattern. Does that fit your needs?
I think its context related, but its worth a shot for sure.
http://en.wikipedia.org/wiki/State_pattern
This let your states decide where to go and not the "object" class.
Bruno
I've just contributed this:
https://code.google.com/p/ysharp/source/browse/#svn%2Ftrunk%2FStateMachinesPoC
Here's one of the examples demoing direct and indirect sending of commands, with states as IObserver(of signal), thus responders to a signal source, IObservable(of signal):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
using Machines;
public static class WatchingTvSampleAdvanced
{
// Enum type for the transition triggers (instead of System.String) :
public enum TvOperation { Plug, SwitchOn, SwitchOff, Unplug, Dispose }
// The state machine class type is also used as the type for its possible states constants :
public class Television : NamedState<Television, TvOperation, DateTime>
{
// Declare all the possible states constants :
public static readonly Television Unplugged = new Television("(Unplugged TV)");
public static readonly Television Off = new Television("(TV Off)");
public static readonly Television On = new Television("(TV On)");
public static readonly Television Disposed = new Television("(Disposed TV)");
// For convenience, enter the default start state when the parameterless constructor executes :
public Television() : this(Television.Unplugged) { }
// To create a state machine instance, with a given start state :
private Television(Television value) : this(null, value) { }
// To create a possible state constant :
private Television(string moniker) : this(moniker, null) { }
private Television(string moniker, Television value)
{
if (moniker == null)
{
// Build the state graph programmatically
// (instead of declaratively via custom attributes) :
Handler<Television, TvOperation, DateTime> stateChangeHandler = StateChange;
Build
(
new[]
{
new { From = Television.Unplugged, When = TvOperation.Plug, Goto = Television.Off, With = stateChangeHandler },
new { From = Television.Unplugged, When = TvOperation.Dispose, Goto = Television.Disposed, With = stateChangeHandler },
new { From = Television.Off, When = TvOperation.SwitchOn, Goto = Television.On, With = stateChangeHandler },
new { From = Television.Off, When = TvOperation.Unplug, Goto = Television.Unplugged, With = stateChangeHandler },
new { From = Television.Off, When = TvOperation.Dispose, Goto = Television.Disposed, With = stateChangeHandler },
new { From = Television.On, When = TvOperation.SwitchOff, Goto = Television.Off, With = stateChangeHandler },
new { From = Television.On, When = TvOperation.Unplug, Goto = Television.Unplugged, With = stateChangeHandler },
new { From = Television.On, When = TvOperation.Dispose, Goto = Television.Disposed, With = stateChangeHandler }
},
false
);
}
else
// Name the state constant :
Moniker = moniker;
Start(value ?? this);
}
// Because the states' value domain is a reference type, disallow the null value for any start state value :
protected override void OnStart(Television value)
{
if (value == null)
throw new ArgumentNullException("value", "cannot be null");
}
// When reaching a final state, unsubscribe from all the signal source(s), if any :
protected override void OnComplete(bool stateComplete)
{
// Holds during all transitions into a final state
// (i.e., stateComplete implies IsFinal) :
System.Diagnostics.Debug.Assert(!stateComplete || IsFinal);
if (stateComplete)
UnsubscribeFromAll();
}
// Executed before and after every state transition :
private void StateChange(IState<Television> state, ExecutionStep step, Television value, TvOperation info, DateTime args)
{
// Holds during all possible transitions defined in the state graph
// (i.e., (step equals ExecutionStep.LeaveState) implies (not state.IsFinal))
System.Diagnostics.Debug.Assert((step != ExecutionStep.LeaveState) || !state.IsFinal);
// Holds in instance (i.e., non-static) transition handlers like this one :
System.Diagnostics.Debug.Assert(this == state);
switch (step)
{
case ExecutionStep.LeaveState:
var timeStamp = ((args != default(DateTime)) ? String.Format("\t\t(# {0})", args) : String.Empty);
Console.WriteLine();
// 'value' is the state value that we are transitioning TO :
Console.WriteLine("\tLeave :\t{0} -- {1} -> {2}{3}", this, info, value, timeStamp);
break;
case ExecutionStep.EnterState:
// 'value' is the state value that we have transitioned FROM :
Console.WriteLine("\tEnter :\t{0} -- {1} -> {2}", value, info, this);
break;
default:
break;
}
}
public override string ToString() { return (IsConstant ? Moniker : Value.ToString()); }
}
public static void Run()
{
Console.Clear();
// Create a signal source instance (here, a.k.a. "remote control") that implements
// IObservable<TvOperation> and IObservable<KeyValuePair<TvOperation, DateTime>> :
var remote = new SignalSource<TvOperation, DateTime>();
// Create a television state machine instance (automatically set in a default start state),
// and make it subscribe to a compatible signal source, such as the remote control, precisely :
var tv = new Television().Using(remote);
bool done;
// Always holds, assuming the call to Using(...) didn't throw an exception (in case of subscription failure) :
System.Diagnostics.Debug.Assert(tv != null, "There's a bug somewhere: this message should never be displayed!");
// As commonly done, we can trigger a transition directly on the state machine :
tv.MoveNext(TvOperation.Plug, DateTime.Now);
// Alternatively, we can also trigger transitions by emitting from the signal source / remote control
// that the state machine subscribed to / is an observer of :
remote.Emit(TvOperation.SwitchOn, DateTime.Now);
remote.Emit(TvOperation.SwitchOff);
remote.Emit(TvOperation.SwitchOn);
remote.Emit(TvOperation.SwitchOff, DateTime.Now);
done =
(
tv.
MoveNext(TvOperation.Unplug).
MoveNext(TvOperation.Dispose) // MoveNext(...) returns null iff tv.IsFinal == true
== null
);
remote.Emit(TvOperation.Unplug); // Ignored by the state machine thanks to the OnComplete(...) override above
Console.WriteLine();
Console.WriteLine("Is the TV's state '{0}' a final state? {1}", tv.Value, done);
Console.WriteLine();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
Note : this example is rather artificial and mostly meant to demo a number of orthogonal features. There should seldomly be a real need to implement the state value domain itself by a full blown class, using the CRTP ( see : http://en.wikipedia.org/wiki/Curiously_recurring_template_pattern ) like this.
Here's for a certainly simpler and likely much more common implementation use case (using a simple enum type as the states value domain), for the same state machine, and with the same test case :
https://code.google.com/p/ysharp/source/browse/trunk/StateMachinesPoC/WatchingTVSample.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test
{
using Machines;
public static class WatchingTvSample
{
public enum Status { Unplugged, Off, On, Disposed }
public class DeviceTransitionAttribute : TransitionAttribute
{
public Status From { get; set; }
public string When { get; set; }
public Status Goto { get; set; }
public object With { get; set; }
}
// State<Status> is a shortcut for / derived from State<Status, string>,
// which in turn is a shortcut for / derived from State<Status, string, object> :
public class Device : State<Status>
{
// Executed before and after every state transition :
protected override void OnChange(ExecutionStep step, Status value, string info, object args)
{
if (step == ExecutionStep.EnterState)
{
// 'value' is the state value that we have transitioned FROM :
Console.WriteLine("\t{0} -- {1} -> {2}", value, info, this);
}
}
public override string ToString() { return Value.ToString(); }
}
// Since 'Device' has no state graph of its own, define one for derived 'Television' :
[DeviceTransition(From = Status.Unplugged, When = "Plug", Goto = Status.Off)]
[DeviceTransition(From = Status.Unplugged, When = "Dispose", Goto = Status.Disposed)]
[DeviceTransition(From = Status.Off, When = "Switch On", Goto = Status.On)]
[DeviceTransition(From = Status.Off, When = "Unplug", Goto = Status.Unplugged)]
[DeviceTransition(From = Status.Off, When = "Dispose", Goto = Status.Disposed)]
[DeviceTransition(From = Status.On, When = "Switch Off", Goto = Status.Off)]
[DeviceTransition(From = Status.On, When = "Unplug", Goto = Status.Unplugged)]
[DeviceTransition(From = Status.On, When = "Dispose", Goto = Status.Disposed)]
public class Television : Device { }
public static void Run()
{
Console.Clear();
// Create a television state machine instance, and return it, set in some start state :
var tv = new Television().Start(Status.Unplugged);
bool done;
// Holds iff the chosen start state isn't a final state :
System.Diagnostics.Debug.Assert(tv != null, "The chosen start state is a final state!");
// Trigger some state transitions with no arguments
// ('args' is ignored by this state machine's OnChange(...), anyway) :
done =
(
tv.
MoveNext("Plug").
MoveNext("Switch On").
MoveNext("Switch Off").
MoveNext("Switch On").
MoveNext("Switch Off").
MoveNext("Unplug").
MoveNext("Dispose") // MoveNext(...) returns null iff tv.IsFinal == true
== null
);
Console.WriteLine();
Console.WriteLine("Is the TV's state '{0}' a final state? {1}", tv.Value, done);
Console.WriteLine();
Console.WriteLine("Press any key...");
Console.ReadKey();
}
}
}
'HTH
FiniteStateMachine is a Simple State Machine, written in C# Link
Advantages tu use my library FiniteStateMachine:
Define a "context" class to present a single interface to the outside world.
Define a State abstract base class.
Represent the different "states" of the state machine as derived classes of the State base class.
Define state-specific behavior in the appropriate State derived classes.
Maintain a pointer to the current "state" in the "context" class.
To change the state of the state machine, change the current "state" pointer.
Download DLL Download
Example on LINQPad:
void Main()
{
var machine = new SFM.Machine(new StatePaused());
var output = machine.Command("Input_Start", Command.Start);
Console.WriteLine(Command.Start.ToString() + "-> State: " + machine.Current);
Console.WriteLine(output);
output = machine.Command("Input_Pause", Command.Pause);
Console.WriteLine(Command.Pause.ToString() + "-> State: " + machine.Current);
Console.WriteLine(output);
Console.WriteLine("-------------------------------------------------");
}
public enum Command
{
Start,
Pause,
}
public class StateActive : SFM.State
{
public override void Handle(SFM.IContext context)
{
//Gestione parametri
var input = (String)context.Input;
context.Output = input;
//Gestione Navigazione
if ((Command)context.Command == Command.Pause) context.Next = new StatePaused();
if ((Command)context.Command == Command.Start) context.Next = this;
}
}
public class StatePaused : SFM.State
{
public override void Handle(SFM.IContext context)
{
//Gestione parametri
var input = (String)context.Input;
context.Output = input;
//Gestione Navigazione
if ((Command)context.Command == Command.Start) context.Next = new StateActive();
if ((Command)context.Command == Command.Pause) context.Next = this;
}
}
I would recommend state.cs. I personally used state.js (the JavaScript version) and am very happy with it. That C# version works in a similar way.
You instantiate states:
// 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" );
...
You instantiate some transitions:
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" ) );
You define actions on states and transitions:
t0.Effect += DisengageHead;
t0.Effect += StopMotor;
And that's (pretty much) it. Look at the website for more information.
There are 2 popular state machine packages in NuGet.
Appccelerate.StateMachine (13.6K downloads + 3.82K of legacy version (bbv.Common.StateMachine))
StateMachineToolkit (1.56K downloads)
The Appccelerate lib has good documentation, but it does not support .NET 4, so I chose StateMachineToolkit for my project.
Other alternative in this repo https://github.com/lingkodsoft/StateBliss
used fluent syntax, supports triggers.
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
}
}
One more state machine for the list, mine: https://github.com/IanMercer/Abodit.StateMachine
In addition to simple states with entry and exit actions, and actions on each transition, this one is designed for use in async code. It also supports hierarchical states and compound state machines. So not really 'simple' but in use it's quite easy to code states and transitions.
static OpenClosedStateMachine()
{
Closed
.When(Fridge.eDoorOpens, (m, s, e, c) => Task.FromResult(Open));
Open
.When(Fridge.eDoorCloses, (m, s, e, c) => Task.FromResult(Closed));
}
Unlike others it also supports temporal transitions so it's easy to transition to a different state After a given period or At a given time.
I too struggled with State Machines when used with a message broker like RabbitMQ or Rabbit.
I created this video to help others.
https://www.youtube.com/watch?v=Vwfngk0YhLs&t=11s&ab_channel=GarryTaylor
Code was from this Github repo
https://github.com/welhell/masstransit-saga-example
I've built a Nuget library that implements a simple and powerful state machine and injectable in DI. You can check it from here Nuget - State Machine
You can use my solution, this is the most convenient way. It’s also free.
Create state machine in three steps :
1. Create scheme in node editor🔗 and load it in your project using library📚
StateMachine stateMachine = new StateMachine("scheme.xml");
2. Describe your app logic on events⚡
stateMachine.GetState("State1").OnExit(Action1);
stateMachine.GetState("State2").OnEntry(Action2);
stateMachine.GetTransition("Transition1").OnInvoke(Action3);
stateMachine.OnChangeState(Action4);
3. Run the state machine🚘
stateMachine.Start();
Links:
Node editor: https://github.com/SimpleStateMachine/SimpleStateMachineNodeEditor
Library: https://github.com/SimpleStateMachine/SimpleStateMachineLibrary

Unique EventId generation

I'm using the Windows Event Log to record some events. Events within the Windows Event Log can be assigned a handful of properties. One of which, is an EventID.
Now I want to use the EventId to try and group related errors. I could just pick a number for each call to the logging method I do, but that seems a little tedious.
I want the system to do this automatically. It would choose an eventId that is "unique" to the position in the code where the logging event occurred. Now, there's only 65536 unique event IDs, so there are likely to be collisions but they should be rare enough to make the EventId a useful way to group errors.
One strategy would be to take the hashcode of the stacktrace but that would mean that the first and second calls in the following code would have generate the same event ID.
public void TestLog()
{
LogSomething("Moo");
// Do some stuff and then a 100 lines later..
LogSomething("Moo");
}
I thought of walking up the call stack using the StackFrame class which has a GetFileLineNumber method. The problem with this strategy is that it will only work when built with debug symbols on. I need it to work in production code too.
Does anyone have any ideas?
Here is some code you can use to generate an EventID with the properties I describe in my question:
public static int GenerateEventId()
{
StackTrace trace = new StackTrace();
StringBuilder builder = new StringBuilder();
builder.Append(Environment.StackTrace);
foreach (StackFrame frame in trace.GetFrames())
{
builder.Append(frame.GetILOffset());
builder.Append(",");
}
return builder.ToString().GetHashCode() & 0xFFFF;
}
The frame.GetILOffset() method call gives the position within that particular frame at the time of execution.
I concatenate these offsets with the entire stacktrace to give a unique string for the current position within the program.
Finally, since there are only 65536 unique event IDs I logical AND the hashcode against 0xFFFF to extract least significant 16-bits. This value then becomes the EventId.
The IL offset number is available without debug symbols. Combined with the stack information and hashed, I think that would do the trick.
Here's an article that, in part, covers retrieving the IL offset (for the purpose of logging it for an offline match to PDB files--different problem but I think it'll show you what you need):
http://timstall.dotnetdevelopersjournal.com/getting_file_and_line_numbers_without_deploying_the_pdb_file.htm
Create a hash using the ILOffset of the last but one stack frame instead of the line number (i.e. the stack frame of your TestLog method above).
*Important: This post focuses at solving the root cause of what it appears your problem is instead of providing a solution you specifically asked for. I realize this post is old, but felt it important to contribute. *
My team had a similar issue, and we changed the way we managed our logging which has reduced production support and bug patching times significantly. Pragmatically this works in most enterprise apps my team works on:
Prefix log messages with the "class name"."function name".
For true errors, output the captured Exception to the event logger.
Focus on having clear messages as part of the peer code review as opposed to event id's.
Use a unique event id for each function, just go top to bottom and key them.
when it becomes impractical to code each function a different event ID, each class should just just have a unique one (collisions be damned).
Utilize Event categories to reduce event id reliance when filtering the log
Of course it matters how big your apps are and how sensitive the data is. Most of ours are around 10k to 500k lines of code with minimally sensitive information. It may feel oversimplified, but from a KISS standpoint it pragmatically works.
That being said, using an abstract Event Log class to simplify the process makes it easy to utilize, although cleanup my be unpleasant. For Example:
MyClass.cs (using the wrapper)
class MyClass
{
// hardcoded, but should be from configuration vars
private string AppName = "MyApp";
private string AppVersion = "1.0.0.0";
private string ClassName = "MyClass";
private string LogName = "MyApp Log";
EventLogAdapter oEventLogAdapter;
EventLogEntryType oEventLogEntryType;
public MyClass(){
this.oEventLogAdapter = new EventLogAdapter(
this.AppName
, this.LogName
, this.AppName
, this.AppVersion
, this.ClassName
);
}
private bool MyFunction() {
bool result = false;
this.oEventLogAdapter.SetMethodInformation("MyFunction", 100);
try {
// do stuff
this.oEventLogAdapter.WriteEntry("Something important found out...", EventLogEntryType.Information);
} catch (Exception oException) {
this.oEventLogAdapter.WriteEntry("Error: " + oException.ToString(), EventLogEntryType.Error);
}
return result;
}
}
EventLogAdapter.cs
class EventLogAdapter
{
//vars
private string _EventProgram = "";
private string _EventSource = "";
private string _ProgramName = "";
private string _ProgramVersion = "";
private string _EventClass = "";
private string _EventMethod = "";
private int _EventCode = 1;
private bool _Initialized = false;
private System.Diagnostics.EventLog oEventLog = new EventLog();
// methods
public EventLogAdapter() { }
public EventLogAdapter(
string EventProgram
, string EventSource
, string ProgramName
, string ProgramVersion
, string EventClass
) {
this.SetEventProgram(EventProgram);
this.SetEventSource(EventSource);
this.SetProgramName(ProgramName);
this.SetProgramVersion(ProgramVersion);
this.SetEventClass(EventClass);
this.InitializeEventLog();
}
public void InitializeEventLog() {
try {
if(
!String.IsNullOrEmpty(this._EventSource)
&& !String.IsNullOrEmpty(this._EventProgram)
){
if (!System.Diagnostics.EventLog.SourceExists(this._EventSource)) {
System.Diagnostics.EventLog.CreateEventSource(
this._EventSource
, this._EventProgram
);
}
this.oEventLog.Source = this._EventSource;
this.oEventLog.Log = this._EventProgram;
this._Initialized = true;
}
} catch { }
}
public void WriteEntry(string Message, System.Diagnostics.EventLogEntryType EventEntryType) {
try {
string _message =
"[" + this._ProgramName + " " + this._ProgramVersion + "]"
+ "." + this._EventClass + "." + this._EventMethod + "():\n"
+ Message;
this.oEventLog.WriteEntry(
Message
, EventEntryType
, this._EventCode
);
} catch { }
}
public void SetMethodInformation(
string EventMethod
,int EventCode
) {
this.SetEventMethod(EventMethod);
this.SetEventCode(EventCode);
}
public string GetEventProgram() { return this._EventProgram; }
public string GetEventSource() { return this._EventSource; }
public string GetProgramName() { return this._ProgramName; }
public string GetProgramVersion() { return this._ProgramVersion; }
public string GetEventClass() { return this._EventClass; }
public string GetEventMethod() { return this._EventMethod; }
public int GetEventCode() { return this._EventCode; }
public void SetEventProgram(string EventProgram) { this._EventProgram = EventProgram; }
public void SetEventSource(string EventSource) { this._EventSource = EventSource; }
public void SetProgramName(string ProgramName) { this._ProgramName = ProgramName; }
public void SetProgramVersion(string ProgramVersion) { this._ProgramVersion = ProgramVersion; }
public void SetEventClass(string EventClass) { this._EventClass = EventClass; }
public void SetEventMethod(string EventMethod) { this._EventMethod = EventMethod; }
public void SetEventCode(int EventCode) { this._EventCode = EventCode; }
}
Thanks for the idea of hashing the call stack, I was going to ask that very same question of how to pick an eventId.
I recommend putting a static variable in LogSomething that increments each time it is called.
Now I want to use the EventId to try
and group related errors.
You have filters in event viewer so why (Go to find ? You have 65536 unique event IDs too.
Or rather use log4net or something ??
just my ideas....

Categories