[C#/Reflectie] FSM architectuur (dmv losse assemblies)

Pagina: 1
Acties:

  • cenix
  • Registratie: September 2001
  • Laatst online: 21-04 18:47
Ik heb een FSM simulatie applicatie die opzich OK werkt, maar in deze applicatie zitten de states, events en de GUI in dezelfde assembly. Ik wil dit opsplitsen, maar loop tegen een probleem waar ik zo niet uitkom.

Ik wil dus een aparte DLL (assembly) voor de FSM specifieke code (states, events & actions),
en de applicatie (die met reflectie die FSM specifieke zaken ophaalt (initial state, events, e.d.).

De GUI moet dus reflecteren op de FSM assembly en de events ophalen, zodat ik deze in mijn GUI kan zien en afvuren. Zoals ik het nu heb moeten zowel de FSM als GUI assembly kennis hebben van de Event enum.

states.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[InitialState]
class TestState : IState
{
  public TestState() {}
  public void Handle(Context c, Event e)
  { // handle event af en ga naar nieuwe state
  }
}

enum Event
{
  EventOne,
  EventTwo
}


GUI.cs
C#:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// dient als 'controller'
class Context
{
  private IState _state;
  public Context()
  {
    
  }
  public IState State
  {
    get { return _state; }
    set { _state = value; }
  }
  public Event FireEvent
  {
    State.Handle(this, value);
  }
}

class UI
{
  // instantieert Context object
  // roept events aan, bv.
  Context c = new Context();
  c.FireEvent = Event.Aan;
}


Zoals te zien is, moet ook de GUI kennis hebben van de states en events. De states vallen met reflectie nog wel uit de assembly te halen en middels het attribuut (InitialStateAttribute) kan ik de FSM opstarten.

Ik weet echter niet hoe ik die events bekend moet maken bij beide assemblies.
Ik heb gepoogd om een shared library te maken die de event enum en de context klasse heeft.
Maar omdat iemand zelf een FSM moet kunnen opbouwen, zonder mijn FSM simulator is dit
geen oplossing.

Hoe moet ik mijn architectuur opbouwen zodat dit goed gaat?

Ik dacht iets als het ophalen van de enum waardes en deze aan de gebruiker tonen. Als de gebruiker een event kiest en afvuurt deze dan naar de context klasse te sturen. Maar dit zijn geen echte events, maar string representaties. Deze strings via Enum.Parse() te versturen.
Maar helaas krijg ik dit niet voor elkaar omdat ik nog kennis moet hebben van de echte enum, omdat je die Enum.Parse() moet casten naar de juiste enum.

Nadeel is wel dat ten alle tijden, alle events voor de gebruiker zichtbaar zijn en niet alleen die events die de huidige state ook werkelijk kan ontvangen.

  • joopst
  • Registratie: Maart 2005
  • Laatst online: 01-10-2024
je kan een configuratiebestand overwegen (xml ofzo)
of het plugin-pattern

  • GrimaceODespair
  • Registratie: December 2002
  • Laatst online: 12:01

GrimaceODespair

eens een tettenman, altijd ...

cenix schreef op woensdag 14 december 2005 @ 14:55:
Deze strings via Enum.Parse() te versturen.
Maar helaas krijg ik dit niet voor elkaar omdat ik nog kennis moet hebben van de echte enum, omdat je die Enum.Parse() moet casten naar de juiste enum.
Als je niet alleen de enum-stringwaarde gebruikt, maar een combinatie van de qualified TypeName en de stringwaarde, kun je die TypeName resolven naar een Type object, en vervolgens Enum.Parse loslaten op die stringwaarde icm met dat Type.

Wij onderbreken deze thread voor reclame:
http://kalders.be


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

enkele scenario's:

- aparte assembly met je FSM + events in.
in je GUI reference je die, en kun je alles gebruiken. je GUI is echter afhankelijk van je FSM logica.
- aparte assembly met FSM
aparte assembly met events en interfaces
GUI referencet FSM en interfaces (of referencet interfaces, en laad FSM dynamisch)
FSM referencet interfaces
- volledig dynamisch met reflection. dit vereist echter meer code en is ook trager.
daarenboven ben je bij verandering gezien voor de moeite.

imo heeft het 2de scenario het meeste voordeel. Je definieert namelijk all inter-assembly communicatie door de interfaces en enum's op te sommen. Daardoor kan je morgen zowel je FSM logica als je GUI veranderen.

ASSUME makes an ASS out of U and ME


  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

Is dat tweede scenario niet gewoon IoC?

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • EfBe
  • Registratie: Januari 2000
  • Niet online
FSM's (of finite state machines voor diegenen die niet zo thuis zijn in acronym bingo), bestaan uit:
- states
- events
- handlers.
- state transition table.

states en events zijn kleine definities, enums zo je wilt. de handlers zijn de routines die je knoopt aan een state. De state transition table geeft de controller de mogelijkheid om een nieuwe state te bepalen mbv current state + event.

States en handlers zijn dus onlosmakelijk met elkaar verbonden, en veelal zijn events daar dan ook weer aan verbonden indien je de handlers events laat genereren. Alles wat aan elkaar is verbonden stop je in 1 assembly.

De state transition table is custom en kun je opbouwen mbv een programma, en je kunt dus een algemene assembly hebben met states, events en handlers en daarnaast die state transition table en je hebt een FSM.

Je kunt ook je events genereren mbv post-handler states. Dit is wat flexibeler en geeft je de ruimte om per state een event table te bouwen die op basis van een post-handler state de events genereert voor je state transition table. post-handler state houdt in: uitvoer van de handler, waarde van globale data structuren etc.

Ik begrijp dus het hele probleem niet zo wat je hebt. Immers, controller in assembly A, states, events en handlers in assembly B. Controller leest state transition table in en kan dan mbv B het programma uitvoeren.

Creator of: LLBLGen Pro | Camera mods for games
Photography portfolio: https://fransbouma.com


  • H!GHGuY
  • Registratie: December 2002
  • Niet online

H!GHGuY

Try and take over the world...

kenneth schreef op woensdag 14 december 2005 @ 18:39:
Is dat tweede scenario niet gewoon IoC?
ja

ASSUME makes an ASS out of U and ME


  • cenix
  • Registratie: September 2001
  • Laatst online: 21-04 18:47
Ik heb het momenteel nu zo opgelost.

Ik heb een assemly FSM waarin ik de states (classes) en de events (enum) heb staan.
Daarnaast heb ik en assembly Shared waarin ik de interface voor de klasses heb staan.
Vervolgens heb ik een assembly waarin ik de context (controller) klasse heb staan en de GUI.
De context (controller) klasse haalt via reflectie de juiste (initial) state op en kan de events opvragen.

Ik heb dus deels het plugin pattern toegepast (alhoewel ik hier niet veel over gevonden heb, lijkt het hier wel op) en deels IoC (Inversion of Control).

bedankt voor het geven van nieuwe inzichten.
Pagina: 1