2011年12月16日金曜日

文字列で指定した VB ソースを実行する

※これは VB Advent Calendat 2011 用の投稿です

Workflow Foundation では Assign アクティビティに代表されるように色々なアクティビティにて VisualBasic 構文を用いた記述が利用できます。この仕組みを利用すると、テキストファイル等に保存した VisualBasic ソースをそのまま解析し実行させることが可能です。


仕組みとしてはステートメントを Assign アクティビティに設定して実行するのですが、この際に考慮する点が何点かあります。

  • 呼び出すメソッドが属するライブラリはなにか
  • 戻り値を利用するか

WF では基本的には .NET で提供されるクラスや自作したクラスを利用する事が可能です。ただしデザイナ上で利用する場合と、コード上で利用する場合とで若干の違いがあります。

デザイナ上では参照設定がある程度自動で補完されるので、あまりライブラリの参照設定を意識する事はありませんが、コード上で同様の事を行った場合は自前の処理にて参照設定を行う必要があり、そこの仕組みは WF 独自の参照設定を利用する事になります。同様にメソッドの戻り値を受取る変数も定義する必要がありますが、これはデザイナ上であろうとコード上であろうと一緒です。

そのあたりを踏まえてサンプルコードはこのような形になります。

   1: Imports System.Activities
   2: Imports System.Activities.Statements
   3: Imports Microsoft.VisualBasic.Activities
   4:  
   5: Module Module1
   6:  
   7:     Sub Main()
   8:         '実行する VB ステートメント
   9:         Const sampleWords1 = "Dim res = Windows.Forms.MessageBox.Show(""Sample Question"",""Sample"",Windows.Forms.MessageBoxButtons.YesNo)"
  10:  
  11:         '参照設定
  12:         Dim newSetting As New VisualBasicSettings
  13:         Dim newRef As New VisualBasicImportReference With {
  14:             .Assembly = "System.Windows.Forms"
  15:         }
  16:         newSetting.ImportReferences.Add(newRef)
  17:  
  18:         'アクティビティの作成
  19:         Dim act As Activity = Nothing
  20:         act = ExecuteFunction(sampleWords1)
  21:         VisualBasic.SetSettings(act, newSetting)
  22:  
  23:         'ワークフローの実行
  24:         Try
  25:             WorkflowInvoker.Invoke(act)
  26:         Catch ex As Exception
  27:             Console.WriteLine(ex.Message)
  28:         End Try
  29:         Console.WriteLine("何かキーを押してください")
  30:         Console.ReadLine()
  31:  
  32:     End Sub
  33:  
  34:     Private Function ExecuteFunction(ByVal words As String) As Activity
  35:         Dim baseAct As New Sequence
  36:  
  37:         Dim word = words.Split("=")
  38:         '変数を Object で定義
  39:         Dim varName = word(0).ToLower.Replace("dim ", "").Trim
  40:         Dim exp = word(1).Trim
  41:         Dim var As New Variable(Of Object) With {.Name = varName}
  42:  
  43:         Dim act As New Assign With {
  44:             .To = New OutArgument(Of Object) With {.Expression = var},
  45:             .Value = New InArgument(Of Object) With {
  46:                 .Expression = New VisualBasicValue(Of Object)(exp)
  47:             }
  48:         }
  49:  
  50:         baseAct.Variables.Add(var)
  51:         baseAct.Activities.Add(act)
  52:  
  53:         Return baseAct
  54:     End Function
  55:  
  56: End Module

上記サンプルは VB2010 Express にてコンソールアプリケーションとして作成しています。プロジェクトの参照設定は System.Activities、System.Activities.Core、System.Activities.Presentation の 3 つを追加しています。

まず参照設定ですが、今回はサンプルとしての手抜きで固定的に System.Windows.Forms.dll の参照設定を追加するようにしています。実際に実行するアクティビティとしては Sequence に内包された Assign という形をとるようにし、Assign にてソースを設定しています。その際、ソース中の [ = ] で文字列を分割し、前方を変数定義、後方をステートメントとしています。

なお、今回は固定的に Assign アクティビティを利用していますが、戻り値のないメソッドを実行する際には InvokeMethod アクティビティを利用します。

そのようにして作成したアクティビティに対して VisualBasic.SetSetting 静的メソッドを呼び出し参照設定を適用しています。
assignsample
このような事をやることによって、文字列で設定された VisualBasic ソースを実行する事ができるようになります。

0 件のコメント:

コメントを投稿