共用方式為


使用活動委派

活動委派可讓活動作者使用特定的簽章以公開回呼,活動使用者可以此為依據來提供活動處理常式。 活動委派有兩種型別可用:ActivityAction<T>,用來定義沒有傳回值的活動委派,以及 ActivityFunc<TResult>,用來定義有傳回值的活動委派。

在限制子活動必須擁有簽章的案例中,活動委派非常實用。 例如,While 活動可包含任何沒有條件約束的子活動型別,但 ForEach<T> 活動的主體是 ActivityAction<T>,且最終由 ForEach<T> 執行的子活動,必須具有與 InArgument<T> 列舉之集合成員相同型別的 ForEach<T>

使用 ActivityAction

有數個 .NET Framework 4.6.1 活動會使用活動的動作,例如 Catch 活動和 ForEach<T> 活動。 在每一個情況下,活動的動作都代表一個位置,工作流程作者會在這裡指定活動,以便在使用其中一個活動撰寫工作流程時提供所要的行為。 在下列範例中,ForEach<T> 活動是用來將文字顯示到主控台視窗。 ForEach<T> 的主體是使用符合字串 ActivityAction<T> 之型別的 ForEach<T> 所指定。 WriteLine 中指定的 Handler 活動擁有繫結至字串值的 Text 引數,該字串值位於 ForEach<T> 活動所反覆查看的集合中。

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);

actionArgument 是用來將集合中的個別項目流動到 WriteLine。 當叫用此工作流程時,主控台就會顯示下列輸出。

HelloWorld.

本主題的範例會使用物件初始化語法。 物件初始化語法在使用程式碼建立工作流程定義時會很有用,因為它會在工作流程中提供活動的階層式檢視,並顯示活動之間的關係。 當您以程式設計方式來建立工作流程時,不一定非得使用物件初始化語法。 下列範例在功能上等同於先前的範例。

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);

如需更多關於物件初始設定式的資訊,請參閱如何初始化物件但不呼叫建構函式 (C# 程式設計指南) 以及如何使用物件初始設定式宣告物件 (Visual Basic)

在下列範例中,TryCatch 活動會用於工作流程中。 ApplicationException 是由工作流程所擲回而且是由 Catch<TException> 活動所處理。 Catch<TException> 活動的活動動作之處理常式是一種 WriteLine 活動,而例外狀況的詳細資料會透過 exDelegateInArgument<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."
    }
};

建立定義 ActivityAction<T> 的自訂活動時,請使用 InvokeAction<T> 來建立該 ActivityAction<T> 的引動過程模型。 在這個範例中,會定義自訂 WriteLineWithNotification 活動。 此活動是由包含 Sequence 活動的 WriteLine 所構成,此活動之後是採用一個字串引數來叫用 InvokeAction<T>ActivityAction<T>

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))
                }
            }
        };
    }
}

使用 WriteLineWithNotification 活動建立工作流程時,工作流程作者會在活動動作的 Handler 中指定想要的自訂邏輯。 在此範例中,會使用 WriteLineWithNotification 活動建立工作流程,且 WriteLine 活動會用來當做 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.

提供多個泛型版本的 InvokeAction<T>ActivityAction<T>,以傳遞一個或多個引數。

使用 ActivityFunc

當活動沒有結果值時,ActivityAction<T> 會非常實用。當傳回結果值時,將會使用 ActivityFunc<TResult>。 建立定義 ActivityFunc<TResult> 的自訂活動時,請使用 InvokeFunc<TResult> 來建立該 ActivityFunc<TResult> 的引動過程模型。 在下列範例中,會定義 WriteFillerText 活動。 若要提供填入文字,應指定 InvokeFunc<TResult> 採用整數引數,並具有字串結果。 一旦擷取了填入文字之後,就會使用 WriteLine 活動將它顯示到主控台。

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)
                }
            }
        };
    }
}

若要提供文字,必須使用活動以採用一個 int 引數,並具有字串結果。 此範例顯示符合要求的 TextGenerator 活動。

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();
    }
}

若要與 TextGenerator 活動共同使用 WriteFillerText 活動,請將它指定為 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);