Utilizzo di delegati di attivitàUsing Activity Delegates

I delegati di attività consentono agli autori di attività di esporre callback con firme specifiche, per cui gli utenti dell'attività possono fornire gestori in base all'attività.Activity delegates enable activity authors to expose callbacks with specific signatures, for which users of the activity can provide activity-based handlers. Sono disponibili due tipi di delegati di attività: ActivityAction<T>, usato per definire i delegati di attività senza un valore restituito, e ActivityFunc<TResult>, usato per definire i delegati di attività con un valore restituito.Two types of activity delegates are available: ActivityAction<T> is used to define activity delegates that do not have a return value, and ActivityFunc<TResult> is used to define activity delegates that do have a return value.

I delegati di attività sono utili in scenari in cui un'attività figlio deve disporre di una determinata firma.Activity delegates are useful in scenarios where a child activity must be constrained to having a certain signature. Ad esempio, un'attività While può contenere qualsiasi tipo di attività figlio senza vincoli, ma il corpo di un'attività ForEach<T> è un oggetto ActivityAction<T> e l'attività figlio che viene eseguita alla fine dall'oggetto ForEach<T> deve disporre di un oggetto InArgument<T> dello stesso tipo dei membri della raccolta enumerata dall'oggetto ForEach<T>.For example, a While activity can contain any type of child activity with no constraints, but the body of a ForEach<T> activity is an ActivityAction<T>, and the child activity that is ultimately executed by ForEach<T> must have an InArgument<T> that is the same type of the members of the collection that the ForEach<T> enumerates.

Uso di ActivityActionUsing ActivityAction

Diverse attività .NET Framework 4.6.1.NET Framework 4.6.1 usano le azioni di attività, ad esempio le attività Catch e ForEach<T>.Several .NET Framework 4.6.1.NET Framework 4.6.1 activities use activity actions, such as the Catch activity and the ForEach<T> activity. In ogni caso, l'azione di attività rappresenta un percorso in cui l'autore del flusso di lavoro specifica un'attività per fornire il comportamento desiderato quando si crea un flusso di lavoro usando una di queste attività.In each case, the activity action represents a location where the workflow author specifies an activity to provide the desired behavior when composing a workflow using one of these activities. Nell'esempio seguente, si usa un'attività ForEach<T> per visualizzare il testo nella finestra della console.In the following example, a ForEach<T> activity is used to display text to the console window. Il corpo dell'oggetto ForEach<T> viene specificato tramite un oggetto ActivityAction<T> che corrisponde al tipo dell'oggetto ForEach<T> che è una stringa.The body of the ForEach<T> is specified by using an ActivityAction<T> that matches the type of the ForEach<T> which is string. L'argomento WriteLine dell'attività Handler specificata nell'oggetto Text è associato ai valori stringa della raccolta scorsa dall'attività ForEach<T>.The WriteLine activity specified in the Handler has its Text argument bound to the string values in the collection that the ForEach<T> activity iterates.

DelegateInArgument<string> actionArgument = new DelegateInArgument<string>();

Activity wf = new ForEach<string>
{
    Body = new ActivityAction<string>
    {
        Argument = actionArgument,
        Handler = new WriteLine
        {
            Text = new InArgument<string>(actionArgument)
        }
    }
};

List<string> items = new List<string>();
items.Add("Hello");
items.Add("World.");

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Values", items);

WorkflowInvoker.Invoke(wf, inputs);

L'oggetto ActionArgument è usato per propagare i singoli elementi della raccolta in WriteLine.The actionArgument is used to flow the individual items in the collection to the WriteLine. 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.

HelloWorld.

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.

DelegateInArgument<string> actionArgument = new DelegateInArgument<string>();

WriteLine output = new WriteLine();
output.Text = new InArgument<string>(actionArgument);

ActivityAction<string> body = new ActivityAction<string>();
body.Argument = actionArgument;
body.Handler = output;

ForEach<string> wf = new ForEach<string>();
wf.Body = body;

List<string> items = new List<string>();
items.Add("Hello");
items.Add("World.");

Dictionary<string, object> inputs = new Dictionary<string, object>();
inputs.Add("Values", items);

WorkflowInvoker.Invoke(wf, inputs);

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.

Nell'esempio seguente, un'attività TryCatch è usata in un flusso di lavoro.In the following example, a TryCatch activity is used in a workflow. Un'eccezione ApplicationException viene generata dal flusso di lavoro e gestita da un'attività Catch<TException>.An ApplicationException is thrown by the workflow, and is handled by a Catch<TException> activity. Il gestore per il Catch<TException> azione dell'attività è un WriteLine attività e i dettagli dell'eccezione vengono propagati mediante il ex DelegateInArgument<T>.The handler for the Catch<TException> activity's activity action is a WriteLine activity, and the exception detail is flowed through to it using the ex DelegateInArgument<T>.

DelegateInArgument<ApplicationException> ex = new DelegateInArgument<ApplicationException>()
{
    Name = "ex"
};

Activity wf = new TryCatch
{
    Try = new Throw()
    {
        Exception = new InArgument<Exception>((env) =>new ApplicationException("An ApplicationException was thrown."))
    },
    Catches = 
    {
        new Catch<ApplicationException>
        {
            Action = new ActivityAction<ApplicationException>
            {
                Argument = ex,
                Handler = new WriteLine()
                {
                    Text = new InArgument<string>((env) => ex.Get(env).Message)
                }
            }
        }
    },
    Finally = new WriteLine()
    {
        Text = "Executing in Finally."
    }
};

Quando si crea un'attività personalizzata che definisce un oggetto ActivityAction<T>, usare un oggetto InvokeAction<T> per modellare la chiamata di tale oggetto ActivityAction<T>.When creating a custom activity that defines an ActivityAction<T>, use an InvokeAction<T> to model the invocation of that ActivityAction<T>. In questo esempio viene definita un'attività WriteLineWithNotification personalizzata.In this example, a custom WriteLineWithNotification activity is defined. Questa attività è costituita da un oggetto Sequence che contiene un'attività WriteLine seguita da un oggetto InvokeAction<T> che richiama un oggetto ActivityAction<T> che accetta un argomento di tipo stringa.This activity is composed of a Sequence that contains a WriteLine activity followed by an InvokeAction<T> that invokes an ActivityAction<T> that takes one string argument.

public class WriteLineWithNotification : Activity
{
    public InArgument<string> Text { get; set; }
    public ActivityAction<string> TextProcessedAction { get; set; }

    public WriteLineWithNotification()
    {
        this.Implementation = () => new Sequence
        {
            Activities = 
            {
                new WriteLine
                {
                    Text = new InArgument<string>((env) => Text.Get(env))
                },
                new InvokeAction<string>
                {
                    Action = TextProcessedAction,
                    Argument = new InArgument<string>((env) => Text.Get(env))
                }
            }
        };
    }
}

Quando un flusso di lavoro viene creato usando l'attività WriteLineWithNotification, l'autore del flusso di lavoro specifica la logica personalizzata desiderata nella proprietà Handler dell'azione dell'attività.When a workflow is created by using the WriteLineWithNotification activity, the workflow author specifies the desired custom logic in the activity action’s Handler. In questo esempio viene creato un flusso di lavoro che usa l'attività WriteLineWithNotification e un'attività WriteLine viene usata come proprietà Handler.In this example, a workflow is created that use the WriteLineWithNotification activity, and a WriteLine activity is used as the Handler.

// Create and invoke the workflow without specifying any activity action
// for TextProcessed.
Activity wf = new WriteLineWithNotification
{
    Text = "Hello World."
};

WorkflowInvoker.Invoke(wf);

// Output:
// Hello World.

// Create and Invoke the workflow with specifying an activity action
// for TextProcessed.
DelegateInArgument<string> msg = new DelegateInArgument<string>();
Activity wf2 = new WriteLineWithNotification
{
    Text = "Hello World with activity action.",
    TextProcessedAction = new ActivityAction<string>
    {
        Argument = msg,
        Handler = new WriteLine
        {
            Text = new InArgument<string>((env) => "Handler of: " + msg.Get(env))
        }
    }
};

// Invoke the workflow with an activity action specified
WorkflowInvoker.Invoke(wf2);

// Output:
// Hello World with activity action.
// Handler of: Hello World with activity action. 

Sono disponibili più versioni generiche degli oggetti InvokeAction<T> e ActivityAction<T> forniti per passare uno o più argomenti.There are multiple generic versions of InvokeAction<T> and ActivityAction<T> provided for passing one or more arguments.

Uso di ActivityFuncUsing ActivityFunc

L'oggetto ActivityAction<T> è utile quando l'attività non restituisce alcun valore di risultato, mentre l'oggetto ActivityFunc<TResult> è usato quando viene restituito un valore di risultato.ActivityAction<T> is useful when there is no result value from the activity, and ActivityFunc<TResult> is used when a result value is returned. Quando si crea un'attività personalizzata che definisce un oggetto ActivityFunc<TResult>, usare un oggetto InvokeFunc<TResult> per modellare la chiamata di tale oggetto ActivityFunc<TResult>.When creating a custom activity that defines an ActivityFunc<TResult>, use an InvokeFunc<TResult> to model the invocation of that ActivityFunc<TResult>. Nell'esempio seguente viene definita un'attività WriteFillerText.In the following example, a WriteFillerText activity is defined. Per fornire il testo di riempimento, viene specificato un oggetto InvokeFunc<TResult> che accetta un argomento Integer e dispone di un risultato di stringa.To supply the filler text, an InvokeFunc<TResult> is specified that takes an integer argument and has a string result. Una volta recuperato il testo di riempimento, viene visualizzato nella console tramite un'attività WriteLine.Once the filler text is retrieved, it is displayed to the console using a WriteLine activity.

public class WriteFillerText : Activity
{
    public ActivityFunc<int, string> GetText { get; set; }
    public InArgument<int> Quantity { get; set; }

    Variable<string> text = new Variable<string>
    {
        Name = "Text"
    };

    public WriteFillerText()
    {
        this.Implementation = () => new Sequence
        {
            Variables = 
            {
                text
            },
            Activities =
            {
                new InvokeFunc<int, string>
                {
                    Func = GetText,
                    Argument = new InArgument<int>((env) => Quantity.Get(env)),
                    Result = new OutArgument<string>(text)
                },
                new WriteLine
                {
                    Text = new InArgument<string>(text)
                }
            }
        };
    }
}

Per fornire il testo, è necessario usare un'attività che accetta un argomento int e dispone di un risultato di stringa.To supply the text, an activity must be used that takes one int argument and has a string result. In questo esempio viene mostrata un'attività TextGenerator che soddisfa questi requisiti.This example shows a TextGenerator activity that meets these requirements.

public class TextGenerator : CodeActivity<string>
{
    public InArgument<int> Quantity { get; set; }
    public InArgument<string> Text { get; set; }

    protected override string Execute(CodeActivityContext context)
    {
        // Provide a quantity of Random Text
        int q = Quantity.Get(context);
        if (q < 1)
        {
            q = 1;
        }

        string text = Text.Get(context) + " ";
        StringBuilder sb = new StringBuilder(text.Length * q);
        for (int i = 0; i < q; i++)
        {
            sb.Append(text);
        }

        return sb.ToString();
    }
}

Per usare l'attività TextGenerator con l'attività WriteFillerText, specificarla come proprietà Handler.To use the TextGenerator activity with the WriteFillerText activity, specify it as the Handler.

DelegateInArgument<int> actionArgument = new DelegateInArgument<int>();

Activity wf = new WriteFillerText
{
    Quantity = 5,
    GetText = new ActivityFunc<int, string>
    {
        Argument = actionArgument,
        Handler = new TextGenerator
        {
            Quantity = new InArgument<int>(actionArgument),
            Text = "Hello World."
        }
    }
};

WorkflowInvoker.Invoke(wf);

Vedere ancheSee Also

Esposizione e richiamo di ActivityActionExposing and Invoking ActivityActions