Creazione di flussi di lavoro, attività ed espressioni tramite codice imperativoAuthoring Workflows, Activities, and Expressions Using Imperative Code

Una definizione del flusso di lavoro è un albero degli oggetti attività configuratiA workflow definition is a tree of configured activity objects. che può essere definita in diversi modi, ad esempio modificando manualmente il codice XAML o usando l'utilità di progettazione del flusso di lavoro per produrre codice XAML.This tree of activities can be defined many ways, including by hand-editing XAML or by using the Workflow Designer to produce XAML. L'utilizzo di XAML tuttavia non è un requisito.Use of XAML, however, is not a requirement. Le definizioni del flusso di lavoro possono essere create anche a livello di codice.Workflow definitions can also be created programmatically. In questo argomento viene fornita una panoramica sulla creazione di definizioni del flusso di lavoro, di attività e di espressioni tramite codice.This topic provides an overview of creating workflow definitions, activities, and expressions by using code. Per esempi di utilizzo di flussi di lavoro XAML mediante il codice, vedere la serializzazione di flussi di lavoro e attività da e verso XAML.For examples of working with XAML workflows using code, see Serializing Workflows and Activities to and from XAML.

Creazione di definizioni del flusso di lavoroCreating Workflow Definitions

È possibile creare una definizione del flusso di lavoro creando un'istanza di un tipo di attività e configurando le proprietà dell'oggetto attività.A workflow definition can be created by instantiating an instance of an activity type and configuring the activity object’s properties. Per attività che non contengono attività figlio, questa operazione può essere completata usando alcune righe di codice.For activities that do not contain child activities, this can be accomplished using a few lines of code.

Activity wf = new WriteLine
{
    Text = "Hello World."
};

WorkflowInvoker.Invoke(wf);

Nota

Negli esempi del presente argomento viene usato WorkflowInvoker per l'esecuzione dei flussi di lavoro di esempio.The examples in this topic use WorkflowInvoker to run the sample workflows. Per ulteriori informazioni su richiamo di flussi di lavoro, il passaggio di argomenti e le opzioni di hosting diverse che sono disponibili, vedere utilizzo di WorkflowInvoker e WorkflowApplication.For more information about invoking workflows, passing arguments, and the different hosting choices that are available, see Using WorkflowInvoker and WorkflowApplication.

In questo esempio viene creato un flusso di lavoro che è costituito da una singola attività WriteLine.In this example, a workflow that consists of a single WriteLine activity is created. L'argomento WriteLine dell'attività Text viene impostato e il flusso di lavoro viene richiamato.The WriteLine activity’s Text argument is set, and the workflow is invoked. Se un'attività contiene attività figlio, il metodo di costruzione è simile.If an activity contains child activities, the method of construction is similar. Nell'esempio seguente viene usata un'attività Sequence che contiene due attività WriteLine.The following example uses a Sequence activity that contains two WriteLine activities.

Activity wf = new Sequence
{
    Activities =
    {
        new WriteLine
        {
            Text = "Hello"
        },
        new WriteLine
        {
            Text = "World."
        }
    }
};

WorkflowInvoker.Invoke(wf);

Uso di inizializzatori di oggettiUsing Object Initializers

Negli esempi di questo argomento viene usata la sintassi di inizializzazione oggettiThe examples in this topic use object initialization syntax. che può essere utile per creare definizioni del flusso di lavoro in codice in quanto fornisce una visualizzazione gerarchica delle attività nel flusso di lavoro e consente di illustrare la relazione tra le attività.Object initialization syntax can be a useful way to create workflow definitions in code because it provides a hierarchical view of the activities in the workflow and shows the relationship between the activities. Non è previsto alcun requisito per usare la sintassi di inizializzazione oggetti quando si creano flussi di lavoro a livello di codice.There is no requirement to use object initialization syntax when you programmatically create workflows. L'esempio seguente rappresenta l'equivalente funzionale dell'esempio precedente.The following example is functionally equivalent to the previous example.

WriteLine hello = new WriteLine();
hello.Text = "Hello";

WriteLine world = new WriteLine();
world.Text = "World";

Sequence wf = new Sequence();
wf.Activities.Add(hello);
wf.Activities.Add(world);

WorkflowInvoker.Invoke(wf);

Per ulteriori informazioni sugli inizializzatori di oggetti, vedere procedura: inizializzare oggetti senza chiamare un costruttore (Guida per programmatori c#) e procedura: dichiarare un oggetto usando un inizializzatore di oggetto.For more information about object initializers, see How to: Initialize Objects without Calling a Constructor (C# Programming Guide) and How to: Declare an Object by Using an Object Initializer.

Uso di variabili, valori letterali ed espressioniWorking with Variables, Literal Values, and Expressions

Quando si crea una definizione del flusso di lavoro tramite codice, prestare attenzione a quale parte di codice viene eseguita per la creazione della definizione del flusso di lavoro e a quale invece per l'esecuzione di un'istanza di quel flusso di lavoro.When creating a workflow definition using code, be aware of what code executes as part of the creation of the workflow definition and what code executes as part of the execution of an instance of that workflow. Ad esempio il flusso di lavoro seguente viene usato per generare un numero casuale e scriverlo nella console.For example, the following workflow is intended to generate a random number and write it to the console.

Variable<int> n = new Variable<int>
{
    Name = "n"
};

Activity wf = new Sequence
{
    Variables = { n },
    Activities =
    {
        new Assign<int>
        {
            To = n,
            Value = new Random().Next(1, 101)
        },
        new WriteLine
        {
            Text = new InArgument<string>((env) => "The number is " + n.Get(env))
        }
    }
};

Quando viene eseguito questo codice di definizione del flusso di lavoro, viene effettuata la chiamata all'oggetto Random.Next e il risultato viene archiviato nella definizione del flusso di lavoro come valore letterale.When this workflow definition code is executed, the call to Random.Next is made and the result is stored in the workflow definition as a literal value. È possibile richiamare molte istanze di questo flusso di lavoro e tutte vengono visualizzate con lo stesso numero.Many instances of this workflow can be invoked, and all would display the same number. Per la generazione di numeri casuali durante l'esecuzione del flusso di lavoro, è necessario usare un'espressione che viene valutata ad ogni esecuzione del flusso di lavoro.To have the random number generation occur during workflow execution, an expression must be used that is evaluated each time the workflow runs. Nell'esempio seguente riportato di seguito viene usata un'espressione di Visual Basic con un elemento VisualBasicValue<TResult>.In the following example, a Visual Basic expression is used with a VisualBasicValue<TResult>.

new Assign<int>
{
    To = n,
    Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}

L'espressione nell'esempio precedente poteva essere distribuita anche usando un elemento CSharpValue<TResult> e un'espressione C#.The expression in the previous example could also be implemented using a CSharpValue<TResult> and a C# expression.

new Assign<int>  
{  
    To = n,  
    Value = new CSharpValue<int>("new Random().Next(1, 101)")  
}  

Le espressioni C# devono essere compilate prima che il flusso di lavoro che le contiene venga richiamato.C# expressions must be compiled before the workflow containing them is invoked. Se non vengono compilate le espressioni c#, un NotSupportedException viene generata quando il flusso di lavoro viene richiamato con un messaggio simile al seguente: Expression Activity type 'CSharpValue1' richiede la compilazione per l'esecuzione.If the C# expressions are not compiled, a NotSupportedException is thrown when the workflow is invoked with a message similar to the following: Expression Activity type 'CSharpValue1' requires compilation in order to run. Verificare che il flusso di lavoro è stato compilato.' nella maggior parte degli scenari che includono flussi di lavoro creati in Visual Studio in c# le espressioni vengono compilate automaticamente, ma in alcuni scenari, ad esempio i flussi di lavoro di codice, le espressioni c# devono essere compilate manualmente.Please ensure that the workflow has been compiled.` In most scenarios involving workflows created in Visual Studio the C# expressions are compiled automatically, but in some scenarios, such as code workflows, the C# expressions must be manually compiled. Per un esempio di come compilare le espressioni c#, vedere il c# utilizzando espressioni nei flussi di lavoro di codice sezione la espressioni c# argomento.For an example of how to compile C# expressions, see the Using C# expressions in code workflows section of the C# Expressions topic.

VisualBasicValue<TResult> rappresenta un'espressione nella sintassi di Visual Basic che può essere usata come r-value in un'espressione e CSharpValue<TResult> rappresenta un'espressione nella sintassi di C# che può essere usata come r-value in un'espressione.A VisualBasicValue<TResult> represents an expression in Visual Basic syntax that can be used as an r-value in an expression, and a CSharpValue<TResult> represents an expression in C# syntax that can be used as an r-value in an expression. Queste espressioni vengono valutate ad ogni esecuzione dell'attività che le contiene.These expressions are evaluated each time the containing activity is executed. Il risultato dell'espressione viene assegnato alla variabile n del flusso di lavoro e questi risultati vengono utilizzati dalla successiva attività nel flusso di lavoro.The result of the expression is assigned to the workflow variable n, and these results are used by the next activity in the workflow. Per accedere al valore della variabile n del flusso di lavoro in fase di esecuzione, è necessario l'oggetto ActivityContextTo access the value of the workflow variable n at runtime, the ActivityContext is required. al quale è possibile accedere tramite l'espressione lambda seguente.This can be accessed by using the following lambda expression.

Nota

Si noti che entrambi i codici di esempio usano C# come linguaggio di programmazione, ma uno usa un oggetto VisualBasicValue<TResult> e l'altro usa un oggetto CSharpValue<TResult>.Note that both of these code are examples are using C# as the programming language, but one uses a VisualBasicValue<TResult> and one uses a CSharpValue<TResult>. VisualBasicValue<TResult> e CSharpValue<TResult> possono essere usati sia nei progetti C# che in progetti Visual Basic.VisualBasicValue<TResult> and CSharpValue<TResult> can be used in both Visual Basic and C# projects. Per impostazione predefinita, le espressioni create nella finestra di progettazione del flusso di lavoro corrispondono al linguaggio del progetto di hosting.By default, expressions created in the workflow designer match the language of the hosting project. Durante la creazione dei flussi di lavoro nel codice, il linguaggio usato è a discrezione dell'autore del flusso di lavoro.When creating workflows in code, the desired language is at the discretion of the workflow author.

In questi esempi il risultato dell'espressione viene assegnato alla variabile n del flusso di lavoro e questi risultati vengono usati dalla successiva attività nel flusso di lavoro.In these examples the result of the expression is assigned to the workflow variable n, and these results are used by the next activity in the workflow. Per accedere al valore della variabile n del flusso di lavoro in fase di esecuzione, è necessario l'oggetto ActivityContextTo access the value of the workflow variable n at runtime, the ActivityContext is required. al quale è possibile accedere tramite l'espressione lambda seguente.This can be accessed by using the following lambda expression.

new WriteLine
{
    Text = new InArgument<string>((env) => "The number is " + n.Get(env))
}

Per ulteriori informazioni sulle espressioni lambda, vedere espressioni Lambda (Guida per programmatori c#) oppure espressioni Lambda (Visual Basic).For more information about lambda expressions, see Lambda Expressions (C# Programming Guide) or Lambda Expressions (Visual Basic).

Le espressioni lambda non sono serializzabili nel formato XAML.Lambda expressions are not serializable to XAML format. Se viene effettuato un tentativo di serializzare un flusso di lavoro con espressioni lambda, viene generata un'eccezione LambdaSerializationException con il messaggio seguente: "Il flusso di lavoro contiene le espressioni lambda specificate nel codice.If an attempt to serialize a workflow with lambda expressions is made, a LambdaSerializationException is thrown with the following message: "This workflow contains lambda expressions specified in code. Queste espressioni non sono serializzabili in XAML.These expressions are not XAML serializable. Per rendere il flusso di lavoro serializzabile in XAML, usare VisualBasicValue/VisualBasicReference o ExpressionServices.Convert(lambda).In order to make your workflow XAML-serializable, either use VisualBasicValue/VisualBasicReference or ExpressionServices.Convert(lambda). In questo modo le espressioni lambda verranno convertite in attività di espressione."This will convert your lambda expressions into expression activities." Per rendere questa espressione compatibile con XAML, usare l'oggetto ExpressionServices e il metodo Convert, come illustrato nell'esempio seguente.To make this expression compatible with XAML, use ExpressionServices and Convert, as shown in the following example.

new WriteLine
{
    //Text = new InArgument<string>((env) => "The number is " + n.Get(env))
    Text = ExpressionServices.Convert((env) => "The number is " + n.Get(env))
}

Si può usare anche un oggetto VisualBasicValue<TResult>.A VisualBasicValue<TResult> could also be used. Si noti che le espressioni lambda non sono obbligatorie quando si usa un'espressione di Visual Basic.Note that no lambda expression is required when using a Visual Basic expression.

new WriteLine
{
    //Text = new InArgument<string>((env) => "The number is " + n.Get(env))
    //Text = ExpressionServices.Convert((env) => "The number is " + n.Get(env))
    Text = new VisualBasicValue<string>("\"The number is \" + n.ToString()")
}

In fase di runtime, le espressioni di Visual Basic vengono compilate nelle espressioni LINQ.At run time, Visual Basic expressions are compiled into LINQ expressions. Entrambi gli esempi precedenti sono serializzabili in XAML, ma se si intende visualizzare e modificare il codice XAML serializzato nella finestra di progettazione del flusso di lavoro, usare VisualBasicValue<TResult> per le espressioni.Both of the previous examples are serializable to XAML, but if the serialized XAML is intended to be viewed and edited in the workflow designer, use VisualBasicValue<TResult> for your expressions. I flussi di lavoro serializzati che usano ExpressionServices.Convert possono essere aperti nella finestra di progettazione, ma il valore dell'espressione sarà vuoto.Serialized workflows that use ExpressionServices.Convert can be opened in the designer, but the value of the expression will be blank. Per ulteriori informazioni sulla serializzazione di flussi di lavoro in XAML, vedere la serializzazione di flussi di lavoro e attività da e verso XAML.For more information about serializing workflows to XAML, see Serializing Workflows and Activities to and from XAML.

Espressioni letterali e tipi riferimentoLiteral Expressions and Reference Types

Le espressioni letterali sono rappresentate nei flussi di lavoro dall'attività Literal<T>.Literal expressions are represented in workflows by the Literal<T> activity. Le seguenti attività WriteLine sono equivalenti a livello funzionale.The following WriteLine activities are functionally equivalent.

new WriteLine  
{  
    Text = "Hello World."  
},  
new WriteLine  
{  
    Text = new Literal<string>("Hello World.")  
}  

Non è valido inizializzare un'espressione letterale con qualsiasi tipo di riferimento eccetto String.It is invalid to initialize a literal expression with any reference type except String. Nell'esempio riportato di seguito, la proprietà Assign di un'attività Value viene inizializzata con un'espressione letterale usando List<string>.In the following example, an Assign activity's Value property is initialized with a literal expression using a List<string>.

new Assign  
{  
    To = new OutArgument<List<string>>(items),  
    Value = new InArgument<List<string>>(new List<string>())  
},  

Quando il flusso di lavoro che contiene questa attività viene convalidato, viene restituito il seguente errore di convalida: “Il valore letterale supporta solo tipi di valore e il tipo non modificabile System.String.When the workflow containing this activity is validated, the following validation error is returned: "Literal only supports value types and the immutable type System.String. Impossibile usare System.Collections.Generic.List`1[System.String] come valore letterale".The type System.Collections.Generic.List`1[System.String] cannot be used as a literal." Se il flusso di lavoro viene richiamato, viene generata un'eccezione InvalidWorkflowException contenente il testo dell'errore di convalida.If the workflow is invoked, an InvalidWorkflowException is thrown that contains the text of the validation error. Si tratta di un errore di convalida perché la creazione di un'espressione letterale con un tipo di riferimento non crea una nuova istanza del tipo di riferimento per ogni istanza del flusso di lavoro.This is a validation error because creating a literal expression with a reference type does not create a new instance of the reference type for each instance of the workflow. Per risolvere il problema, sostituire l'espressione letterale con una che crea e restituisce una nuova istanza del tipo di riferimento.To resolve this, replace the literal expression with one that creates and returns a new instance of the reference type.

new Assign  
{  
    To = new OutArgument<List<string>>(items),  
    Value = new InArgument<List<string>>(new VisualBasicValue<List<string>>("New List(Of String)"))  
},  

Per ulteriori informazioni sulle espressioni, vedere espressioni.For more information about expressions, see Expressions.

Chiamata di metodi su oggetti usando le espressioni e l'attività InvokeMethodInvoking Methods on Objects using Expressions and the InvokeMethod Activity

L'attività InvokeMethod<TResult> può essere usata per richiamare i metodi statici e di istanza di classi di .NET Framework.The InvokeMethod<TResult> activity can be used to invoke static and instance methods of classes in the .NET Framework. In un esempio precedente in questo argomento, un numero casuale è stato generato usando la classe Random.In a previous example in this topic, a random number was generated using the Random class.

new Assign<int>
{
    To = n,
    Value = new VisualBasicValue<int>("New Random().Next(1, 101)")
}

Si sarebbe anche potuto usare l'attività InvokeMethod<TResult> per chiamare il metodo Next della classe Random.The InvokeMethod<TResult> activity could also have been used to call the Next method of the Random class.

new InvokeMethod<int>  
{  
    TargetObject = new InArgument<Random>(new VisualBasicValue<Random>("New Random()")),  
    MethodName = "Next",  
    Parameters =   
    {  
        new InArgument<int>(1),  
        new InArgument<int>(101)  
    },  
    Result = n  
}  

Poiché Next non è un metodo statico, un'istanza della classe Random viene fornita per la proprietà TargetObject.Since Next is not a static method, an instance of the Random class is supplied for the TargetObject property. In questo esempio viene creata una nuova istanza usando un'espressione di Visual Basic, ma avrebbe potuto essere creata in precedenza ed essere archiviata in una variabile del flusso di lavoro.In this example a new instance is created using a Visual Basic expression, but it could also have been created previously and stored in a workflow variable. In questo esempio, sarebbe più semplice usare l'attività Assign<T> anziché l'attività InvokeMethod<TResult>.In this example, it would be simpler to use the Assign<T> activity instead of the InvokeMethod<TResult> activity. Se la chiamata al metodo richiamato di recente dalla attività Assign<T> o InvokeMethod<TResult> ha un'esecuzione prolungata, InvokeMethod<TResult> ha un vantaggio poiché dispone di una proprietà RunAsynchronously.If the method call ultimately invoked by either the Assign<T> or InvokeMethod<TResult> activities is long running, InvokeMethod<TResult> has an advantage since it has a RunAsynchronously property. Se questa proprietà è impostata su true, il metodo richiamato verrà eseguito in modo asincrono rispetto al flusso di lavoro.When this property is set to true, the invoked method will run asynchronously with regard to the workflow. Se vi sono altre attività in parallelo, queste non verranno bloccate durante l'esecuzione asincrona del metodo.If other activities are in parallel, they will not be blocked while the method is asynchronously executing. Inoltre, se il metodo da richiamare non ha valore restituito, InvokeMethod<TResult> rappresenta la soluzione appropriata per richiamare il metodo.Also, if the method to be invoked has no return value, then InvokeMethod<TResult> is the appropriate way to invoke the method.

Argomenti e attività dinamicheArguments and Dynamic Activities

Una definizione del flusso di lavoro viene creata in codice assemblando le attività in un albero delle attività e configurando qualsiasi proprietà e argomento.A workflow definition is created in code by assembling activities into an activity tree and configuring any properties and arguments. Gli argomenti esistenti possono essere associati, ma quelli nuovi non possono essere aggiunti alle attività,Existing arguments can be bound, but new arguments cannot be added to activities. inclusi gli argomenti del flusso di lavoro passati all'attività radice.This includes workflow arguments passed to the root activity. In codice imperativo, gli argomenti del flusso di lavoro vengono specificati come proprietà in un nuovo tipo CLR e in XAML vengono dichiarati tramite gli oggetti x:Class e x:Member.In imperative code, workflow arguments are specified as properties on a new CLR type, and in XAML they are declared by using x:Class and x:Member. Poiché non è disponibile alcun nuovo tipo CLR creato quando una definizione del flusso di lavoro viene creata come albero di oggetti in memoria, gli argomenti non possono essere aggiunti.Because there is no new CLR type created when a workflow definition is created as a tree of in-memory objects, arguments cannot be added. Tuttavia, gli argomenti possono essere aggiunti a un oggetto DynamicActivity.However, arguments can be added to a DynamicActivity. In questo esempio viene creato un oggetto DynamicActivity<TResult> che accetta due argomenti Integer, li somma e restituisce il risultato.In this example, a DynamicActivity<TResult> is created that takes two integer arguments, adds them together, and returns the result. Viene creato un oggetto DynamicActivityProperty per ogni argomento e il risultato dell'operazione viene assegnato all'argomento Result dell'oggetto DynamicActivity<TResult>.A DynamicActivityProperty is created for each argument, and the result of the operation is assigned to the Result argument of the DynamicActivity<TResult>.

InArgument<int> Operand1 = new InArgument<int>();
InArgument<int> Operand2 = new InArgument<int>();

DynamicActivity<int> wf = new DynamicActivity<int>
{
    Properties =
    {
        new DynamicActivityProperty
        {
            Name = "Operand1",
            Type = typeof(InArgument<int>),
            Value = Operand1
        },
        new DynamicActivityProperty
        {
            Name = "Operand2",
            Type = typeof(InArgument<int>),
            Value = Operand2
        }
    },

    Implementation = () => new Sequence
    {
        Activities = 
        {
            new Assign<int>
            {
                To = new ArgumentReference<int> { ArgumentName = "Result" },
                Value = new InArgument<int>((env) => Operand1.Get(env) + Operand2.Get(env))
            }
        }
    }
};

Dictionary<string, object> wfParams = new Dictionary<string, object>
{
    { "Operand1", 25 },
    { "Operand2", 15 }
};

int result = WorkflowInvoker.Invoke(wf, wfParams);
Console.WriteLine(result);

Per ulteriori informazioni sulle attività dinamica, vedere creazione di un'attività in fase di esecuzione.For more information about dynamic activities, see Creating an Activity at Runtime.

Attività compilateCompiled Activities

Le attività dinamiche sono un modo per definire tramite codice un'attività che contiene argomenti, ma le attività possono anche essere create nel codice e compilate nei tipi.Dynamic activities are one way to define an activity that contains arguments using code, but activities can also be created in code and compiled into types. È possibile creare attività semplici che derivano da CodeActivitye attività asincrone che derivano da AsyncCodeActivity.Simple activities can be created that derive from CodeActivity, and asynchronous activities that derive from AsyncCodeActivity. Queste attività possono avere argomenti, valori restituiti e definiscono la relativa logica usando il codice imperativo.These activities can have arguments, return values, and define their logic using imperative code. Per esempi di creazione di questi tipi di attività, vedere di una classe Base CodeActivity e la creazione di attività asincrone.For examples of creating these types of activities, see CodeActivity Base Class and Creating Asynchronous Activities.

Le attività che derivano da NativeActivity possono definire la relativa logica usando il codice imperativo possono inoltre contenere attività figlio che definiscono la logica.Activities that derive from NativeActivity can define their logic using imperative code and they can also contain child activities that define the logic. Dispongono inoltre dell'accesso completo alle funzionalità del runtime come la creazione dei segnalibri.They also have full access to the features of the runtime such as creating bookmarks. Per esempi di creazione di un NativeActivity-basato su attività, vedere di una classe Base NativeActivity, come: creare un'attivitàe composta personalizzata tramite l'oggetto Nativeactivityesempio.For examples of creating a NativeActivity-based activity, see NativeActivity Base Class, How to: Create an Activity, and the Custom Composite using Native Activity sample.

Le attività che derivano da Activity definiscono la relativa logica unicamente attraverso l'uso di attività figlio.Activities that derive from Activity define their logic solely through the use of child activities. Queste attività vengono in genere create tramite la finestra di progettazione del flusso di lavoro, ma possono essere definite anche tramite codice.These activities are typically created by using the workflow designer, but can also be defined by using code. Nell'esempio seguente viene definita un'attività Square che deriva da Activity<int>.In the following example, a Square activity is defined that derives from Activity<int>. L'attività Square ha un unico InArgument<T> denominato Value e definisce la relativa logica specificando un'attività Sequence che usa la proprietà Implementation.The Square activity has a single InArgument<T> named Value, and defines its logic by specifying a Sequence activity using the Implementation property. L'attività Sequence contiene un'attività WriteLine e un'attività Assign<T>.The Sequence activity contains a WriteLine activity and an Assign<T> activity. Insieme, queste tre attività implementano la logica dell'attività Square.Together, these three activities implement the logic of the Square activity.

class Square : Activity<int>  
{  
    [RequiredArgument]  
    public InArgument<int> Value { get; set; }  

    public Square()  
    {  
        this.Implementation = () => new Sequence  
        {  
            Activities =  
            {  
                new WriteLine  
                {  
                    Text = new InArgument<string>((env) => "Squaring the value: " + this.Value.Get(env))  
                },  
                new Assign<int>  
                {  
                    To = new OutArgument<int>((env) => this.Result.Get(env)),  
                    Value = new InArgument<int>((env) => this.Value.Get(env) * this.Value.Get(env))  
                }  
            }  
        };  
    }  
}  

Nell'esempio riportato di seguito, una definizione del flusso di lavoro costituita da un'unica attività Square viene richiamata usando WorkflowInvoker.In the following example, a workflow definition consisting of a single Square activity is invoked using WorkflowInvoker.

Dictionary<string, object> inputs = new Dictionary<string, object> {{ "Value", 5}};  
int result = WorkflowInvoker.Invoke(new Square(), inputs);  
Console.WriteLine("Result: {0}", result);  

Quando il flusso di lavoro viene richiamato, l'output seguente viene visualizzato nella console:When the workflow is invoked, the following output is displayed to the console:

Elevazione al quadrato il valore: 5Squaring the value: 5
Risultato: 25Result: 25