Máquinas de Estado en C# 3.0 usando AjGenesis

Published on Author lopezLeave a comment

Recientemente encontré el trabajo de Andrew Matthews:

Permanent Link to State Machines in C# 3.0 using T4 Templates

Tomé el ejemplo y lo reimplementé usando mi proyecto de generación de código AjGenesis. Para correr este ejemplo, tenemos que bajar la última versión publicada 0.5 desde la página del proyecto en Codeplex.

(más información sobre el proyecto, ejemplos, explicación del funcionamiento en mis anteriores posts).

Pueden bajar el código de este ejemplo.

El modelo que usé es el mismo del post original de Andrew:

<?xml version="1.0" encoding="utf-8" ?> <StateModels> <StateModel ID="My" start="defcon1"> <States> <State ID="defcon1" name="defcon1"/> <State ID="defcon2" name="defcon2"/> <State ID="defcon3" name="defcon3"/> </States> <Inputs> <Input ID="diplomaticIncident" name="diplomaticIncident"/> <Input ID="assassination" name="assassination"/> <Input ID="coup" name="coup"/> </Inputs> <Transitions> <Transition from="defcon1" to="defcon2" on="diplomaticIncident"/> <Transition from="defcon2" to="defcon3" on="assassination"/> <Transition from="defcon3" to="defcon1" on="coup"/> </Transitions> </StateModel> </StateModels>

(Andrew escribió que ha sido influido un poco por la serie de TV 24, al elegir los estados del ejemplo… 😉

Modifiqué la solución original:

Ahora, hay un archivo Model.xml que contiene el modelo de arriba. El archivo MyStateModel.cs es automáticamente generado desde el modelo. Cambié la solución para tener un evento de Pre-Build en el proyecto TestHarness:

$(ProjectDir)..\VsMakeStates.cmd

El archivo .cmd contiene:

cd ..\..\..
c:\ajlopez\ProyectosNet2\AjGenesis-0.5\bin\AjGenesis.Console TestHarness\Model.xml GenStates.ajg

(TENEMOS que cambiar la segunda línea para apuntar al directorio binario de AjGenesis 0.5)

Con este comando, AjGenesis.Console carga el modelo desde el archivo .xml, y aplica una tarea, GenStates.ajg, escrita enwritten in AjBasic:

for each StateModel in StateModels
    TransformerManager.Transform(“State.tpl”,”TestHarness\${StateModel.ID}StateModel.cs”,Environment)
end for

Hay otro comando, que podemos lanzar directamente desde la línea de comando, MakeStates.cmd, conteniendo:

c:\ajlopez\ProyectosNet2\AjGenesis-0.5\bin\AjGenesis.Console TestHarness\Model.xml GenStates.ajg

Amo mi template AjBasic en GenStates.ajg 😉 un fragmento:

using System; using System.Collections.Generic; using Aabs; using Core; namespace ${StateModel.ID} { public enum ${StateModel.ID}States : int { <# sep = "" for each State in StateModel.States #> ${sep}${State.ID} // ${State.name} <# sep = "," end for #> } // end enum ${StateModel.Id}States ...

Está basado en archivo .tt de Andrew Matthews. Notemos que no hay referencia a nodos .XML o similares. AjGenesis carga el modelo en memoria, como un objeto dinámico. El lenguaje AjBasic puede acceder al modelo, usándolo como un objecto cualquiera. El uso de ${ } reemplaza la salida con algún valor, tomado de las variables o del modelo en proceso.

El principal punto en este ejemplo es que está basado en un modelo libre (AjGenesis puede cargar cualquier modelo, no se usa uno predefinido). Si uno quiere agregar más información, podemos escribir más atributos, elementos, en el archivo .xml. Y usarlos desde el código de template. No hay un esquema fijo.

Otro punto a destacar: el ejemplo podría ser modificado para generar la solución Visual Studio completa, o para generar una solución en otro lenguaje (un ejemplo generando una solución VS completa:
Code Generation for LINQ and C# 3.0 with AjGenesis
)

Gracias a Andrés por un ejemplo tan interesante. Pueden leer más sobre su implementación en el post mencionado:

Permanent Link to State Machines in C# 3.0 using T4 Templates

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com
http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *