2012年1月30日月曜日

DynamicActivity によるアクティビティの動的生成と実行

Workflow Foundation では DynamicActivity クラスを利用して、動的にアクティビティを生成する機能が用意されています。利用するシーンとしては、プログラムのロジック内部でアクティビティの挙動を変更させたい場合とか、アクティビティの存在を表に出したくない場合などがあるかと思います。

まずはソースを。

   1: Imports System.Activities
   2: Imports System.Activities.Statements
   3: Imports System.Activities.Expressions
   4:  
   5: Module Module1
   6:  
   7:     Sub Main()
   8:  
   9:         Dim dyAct As New DynamicActivity
  10:         '引数・変数の作成
  11:         Dim addValue1 As New InArgument(Of Integer)
  12:         Dim addValue2 As New InArgument(Of Integer)
  13:         Dim resValue As New OutArgument(Of Integer)
  14:         dyAct.Properties.Add(New DynamicActivityProperty With {
  15:                              .Name = "AVal", .Type = GetType(InArgument(Of Integer)), .Value = addValue1})
  16:         dyAct.Properties.Add(New DynamicActivityProperty With {
  17:                              .Name = "BVal", .Type = GetType(InArgument(Of Integer)), .Value = addValue2})
  18:         dyAct.Properties.Add(New DynamicActivityProperty With {
  19:                              .Name = "ResVal", .Type = GetType(OutArgument(Of Integer)), .Value = resValue})
  20:         '実行するアクティビティの作成
  21:         dyAct.Implementation = New Func(Of Activity)(Function()
  22:                                                          Dim sqAct As New Sequence
  23:                                                          Dim asAct = New Assign(Of Integer) With {
  24:                                                              .Value = New InArgument(Of Integer)(Function(env) addValue1.Get(env) + addValue2.Get(env)),
  25:                                                              .To = New ArgumentReference(Of Integer) With {.ArgumentName = "ResVal"}
  26:                                                          }
  27:                                                          Dim wlAct As New WriteLine With {
  28:                                                              .Text = New InArgument(Of String)(Function(env) resValue.Get(env).ToString)}
  29:                                                          sqAct.Activities.Add(asAct)
  30:                                                          sqAct.Activities.Add(wlAct)
  31:                                                          Return sqAct
  32:                                                      End Function)
  33:         '引数の値を設定
  34:         Dim args As New Dictionary(Of String, Object)
  35:         args.Add("AVal", 10)
  36:         args.Add("BVal", 50)
  37:         '実行
  38:         WorkflowInvoker.Invoke(dyAct, args)
  39:         Console.ReadKey()
  40:  
  41:     End Sub
  42:  
  43: End Module

コメントを適宜挿入してあるので大まかな流れは把握できると思います。

まず最初にアクティビティのプロパティを DynamicActivityProperty クラスを用いて生成します。このあたりはアクティビティのカスタマイズの際にプロパティを追加している作業そのものです。

そして DynamicActivity.Implementation プロパティに対して、実行するロジック=アクティビティを設定します。今回はラムダ式を利用していますが Addressof を利用して設定するのが見やすい事が多いと思います。

生成している実行されるアクティビティとしては、Sequence アクティビティをコンテナとして、変数 AVal と BVal を足し合わせ、変数 ResVal に設定し WriteLine アクティビティにて表示する、という簡単なものです。全てをコーディング上で行っているので、普段見慣れない記述が多くなります。なお、DynamicActivity に対して変数を追加しているので、当然その子供である Sequnce や Assign、WriteLine アクティビティの内部でも動的に追加した変数が利用できています。

このような形で DynamicActivity を利用する事で、プログラム実行時に動的にアクティビティを生成し、それを実行する事が出来ます。

0 件のコメント:

コメントを投稿