Compuesto personalizado utilizando la actividad Native

En el ejemplo de CustomCompositeNativeActivity, se muestra cómo escribir una NativeActivity que programa otros objetos Activity para controlar el flujo de la ejecución de un flujo de trabajo. En este ejemplo se utilizan dos flujos de control comunes, Sequence y While, para mostrar cómo hacerlo.

Detalles del ejemplo

A partir de MySequence, lo primero que debe observar es que deriva de NativeActivity. NativeActivity es el objeto Activity que expone todo el tiempo de ejecución de flujo de trabajo mediante el NativeActivityContext pasado al método Execute.

MySequence expone una colección pública de objetos Activity que rellena el autor del flujo de trabajo. Antes de que se ejecute el flujo de trabajo, el tiempo de ejecución del flujo de trabajo llama al método CacheMetadata en cada actividad de un flujo de trabajo. Durante este proceso, el tiempo de ejecución establece relaciones primarias-secundarias para administrar la duración y el ámbito de los datos. La implementación predeterminada del método CacheMetadata utiliza la clase de instancia TypeDescriptor de la actividad MySequence para agregar cualquier propiedad pública de tipo Activity o IEnumerable<Activity> como elementos secundarios de la actividad MySequence.

Siempre que una actividad expone una colección pública de actividades secundarias, es bastante probable que esas actividades secundarias compartan estado. Es un procedimiento recomendado para la actividad primaria, en este caso MySequence, exponer también una colección de variables que permitan a las actividades secundarias lograrlo. Al igual que ocurre con las actividades secundarias, el método CacheMetadata agrega propiedades públicas de tipo Variable o IEnumerable<Variable> como variables asociadas a la actividad MySequence.

Además de las variables públicas, que son manipuladas por los elementos secundarios de MySequence, MySequence debe realizar también un seguimiento de en qué punto se encuentra en la ejecución de sus elementos secundarios. Para ello, utiliza una variable privada, currentIndex. Esta variable se registra como parte del entorno MySequence agregando una llamada al método AddImplementationVariable dentro del método CacheMetadata de la actividad MySequence. Los objetos Activity agregados a la colección MySequenceActivities no pueden obtener acceso a las variables agregadas de esta manera.

Cuando el tiempo de ejecución ejecuta MySequence, llama a su método Execute, pasando un objeto NativeActivityContext. NativeActivityContext es el proxy de actividad en el tiempo de ejecución para desreferenciar los argumentos y las variables, así como para programar otros objetos Activity o ActivityDelegates. MySequence usa un método InternalExecute para encapsular la lógica de programar el primer elemento secundario y todos los elementos secundarios subsiguientes en un único método. Se inicia desreferenciando el objeto currentIndex. Si es igual al recuento de la colección Activities, se finaliza la secuencia, la actividad devuelve sin programar cualquier trabajo y el tiempo de ejecución pasa al estado Closed. Si currentIndex es menor que el recuento de actividades, el elemento secundario siguiente se obtiene de la colección Activities y MySequence llama a ScheduleActivity, pasando el elemento secundario que se va a programar y CompletionCallback que apunta al método InternalExecute. Por último, currentIndex se incrementa y el control se devuelve al tiempo de ejecución. Mientras una instancia de MySequence tenga un objeto secundario Activity programado, el motor de ejecución considerará que su estado es En ejecución.

Cuando la actividad secundaria se completa, se ejecuta CompletionCallback. El bucle continúa desde el principio. Al igual que Execute, CompletionCallback toma un objeto NativeActivityContext, otorgando al implementador acceso al tiempo de ejecución.

MyWhile difiere de MySequence en que programa un objeto Activity único de manera repetida y en que utiliza un objeto Activity<TResult><bool> denominado Condition para determinar si se debería producir esta programación. Al igual que MySequence, MyWhile utiliza un método InternalExecute para centralizar su lógica de programación. Programa el objeto ConditionActivity<bool> con un objeto CompletionCallback<TResult><bool> denominado OnEvaluationCompleted. Cuando se completa la ejecución de Condition, su resultado pasa a estar disponible a través de CompletionCallback en un parámetro fuertemente tipado denominado result. Si true, MyWhile llama a ScheduleActivity, pasando el objeto BodyActivity y InternalExecute como CompletionCallback. Cuando la ejecución de Body se completa, Condition se vuelve a programar en InternalExecute, lo que inicia de nuevo el bucle. Cuando Condition devuelve false, una instancia de MyWhile devuelve el control al tiempo de ejecución sin programar el objeto Body y el tiempo de ejecución pasa al estado Closed.

Configurar, compilar y ejecutar el ejemplo

  1. Abra la solución de prueba Composite.sln en Visual Studio.

  2. Compile y ejecute la solución.