2011年4月21日木曜日

StateMachine 関連アクティビティ

先日 .NET Framework 4 Platform Update 1 がリリースされ、今まで CodePlex で公開されていた Statemachine アクティビティ関係が正式に採用されました。同時に UnitTesting 関係のライブラリも採用されていたりと、Workflow 使いにはなかなか嬉しい更新です。

・・・が、自分の環境ではそれらのパッチが適用されてくれないので実物には触れてません。

調べているとどうやら CodePlex のものをベースに名前空間が変わった点と、機能強化されている点が追加されているとのことですので、今までの CTP 版を触っておくことも無意味ではないと信じたいのもあり、少しばかり触ってみました。

まずCTP版をリホスティング環境で利用するには少々事前準備が必要です。関係するdllの参照設定はいいとして、メタデータの更新が必要になります。

  1: Dim smReg As New Microsoft.Activities.Statements.Design.DesignerMetadata
  2: smReg.Register()


ロジックとしては上記の通りになります。そしてToolBoxItemとして登録するクラスも少々注意が必要です。




  • .Microsoft.Activities.Statements.Design.ToolboxItems.StateMachineWithInitialStateFactory:StateMachine アクティビティ


  • Microsoft.Activities.Statements.State:State アクティビティ


  • Microsoft.Activities.Statements.Design.ToolboxItems.FinalState:FinalState アクティビティ



StateMachine アクティビティと FinalState アクティビティのみ特殊になります。



大雑把にいうと、StateMachine アクティビティは本体、State アクティビティはその内部で状態毎に用意するアクティビティ、FinalState アクティビティは終了点です。そしてツールボックス上には用意できませんが、Transition アクティビティというものがあります。これは State アクティビティより別アクティビティに対して引かれる線になります。それぞれの設定については次回以降の記事に書きますが、利用シーンとしてこのような形が考えられる、というサンプルを貼っておきます。



StateMachineSample



状態とその遷移を上手くまとめられると、非常に使い出のある Workflow になると感じています。

2011年4月20日水曜日

FlowDecision と FlowSwitch アクティビティ

前述したように FLowchart アクティビティの子としてのみ利用できる特殊なアクティビティとして、FlowDecision と FlowSwitch の二つが用意されています。どちらも条件分岐を行うのですが、FlowDecision アクティビティが「式の結果による二分岐」なのに対して、FlowSwitch アクティビティは「対象に対しての複数分岐」と微妙に設定内容が異なります。ただこれも、プログラミングを行われている方であればイメージしやすく、FlowDecision アクティビティは IF 文、FlowSwitch アクティビティは Switch ( VB であれば Select Case ) 文による多分岐となります。

FlowDecision

FlowDecision アクティビティでは Condition プロパティに判断を行う「式」を設定します。この式は結果が True か False になる必要があります。サンプル例では [ 変数 var1 が “9” かどうか ] という判断を行い、True であれば向かって左側に、False であれば向かって右側に制御が遷移していきます。なお FlowDecision アクティビティから出ている線上に「True」「False」とありますが、ここの表示される文言は TrueLabel、FalseLabel プロパティで設定できます。

FlowSwitch

FlowSwitch アクティビティは対象となる変数等を Expression プロパティに設定します。サンプルでは var2 という変数を設定しています。これは直前のアクティビティで適当に値を入力させた結果を設定しています。

FlowSwitch2

そして FlowSwitch アクティビティから分岐するアクティビティへと線を伸ばして結合させます。その「線」に対して条件を設定する形になります。Case プロパティでは FlowSwitch の Expression プロパティに対しての値を設定し、その条件が満たされた場合に接続先のアクティビティが実行されます。IsDefaultCase プロパティは「他条件が満たされない場合」に遷移する線かどうか、を設定します。これは FlowSwitch アクティビティ1つに対して1本だけ存在できます。Select Case 文で言えば Case Else、Switch 文で言えばそのまま Default になります。

ちなみに Select Case True、として Case A = B などという設定についてですが、今のところはできません。カスタマイズが必要になると思いますが、ワークフローを使うのであれば、そういった微妙な技は使わない方がいいと思います・・・。

Flowchart アクティビティ

標準提供の中でも特殊なものの一つが Flowchart アクティビティです。名前がそのものずばりですので、イメージも付きやすいかと思いますがフローチャート制御を行うためのアクティビティです。実際に利用した際のサンプルとしてはこのような形になります。

Flowchart1

今までのアクティビティは Sequence アクティビティの子として設定していたのもあり、直線的な流れによる制御でした。ですが Flowchart アクティビティを利用した場合は、まさしくフローチャートによる制御が行えます。昔はプログラムを考える際にフローチャートは結構当たり前だったので、ある程度年齢を重ねた方でしたら問題ないとは思いますが、今は知らない人も多いというか、フローチャートでロジック構造を考える、というのが合わなくなってきているのもあるかと思います。

Flowchart アクティビティを利用した際、一番大きなメリットは「制御の先頭に戻る」等の制御が非常に記述しやすい点です。無限ループも簡単に用意できますw サンプルで用意したワークフローにおいても、条件を満たさなければずっと False 側の制御をぐるぐる回るというひどいものです。

なお見ていただいてわかるように、Flowchart アクティビティを利用するからと言っても今までのアクティビティが利用できないわけではありません。Flowchart アクティビティの子として Sequence アクティビティを用意したり、反対に Sequence アクティビティの子として Flowchart アクティビティを利用する、というように非常に柔軟に利用できます。

ただし Flowchart アクティビティの子としてのみ利用できる特殊なアクティビティがありますので、そこを次あたりで書きたいと思います。

2011年4月19日火曜日

Collection 操作のアクティビティ

標準で提供されているアクティビティの中でコレクション操作用のアクティビティがあります。

  • AddToCollection<T> アクティビティ
  • ClearCollection<T> アクティビティ
  • ExistsInCollection<T> アクティビティ
  • RemoveFromCollection<T> アクティビティ

名前からなんとなくイメージがつくかとは思います。AddToCollection アクティビティはコレクションに値を追加、RemoveFromCollection アクティビティはコレクションから値を除去、ExistsInCollection アクティビティはコレクションの中に対象が存在するかのチェック、ClearCollection アクティビティはコレクションのクリア、をそれぞれ行います。

WFCollection2

AddToCollection アクティビティの設定はこのような感じです。Collection プロパティに操作対象のコレクション変数を指定、Item プロパティで追加する値、TypeArgument プロパティは追加するものの Type を指定します。

WFCollection3

ExistsInCollection アクティビティはこのような感じです。AddToCollection アクティビティとほぼ同様のプロパティですが、Result プロパティが増えています。これは存在したかどうかの結果を受け取る Boolean 型の変数を指定します。

WFCollection4

RemoveFromCollection アクティビティは ExistsInCollection アクティビティと同様のプロパティ構成となっています。

このような形で、設定、利用するのですが一つ当然と言えば当然な注意点があります。それはここで利用するコレクションを初期化するのは自分で行う必要がある、という点です。ワークフロー自体の変数として定義する際に初期値を New String(){“1”,”2”,・・・} 等と固定的に記述するか、Assign アクティビティで同じように記述するか、どちらかを行う必要があります。

これがちょっと面倒なんですよね・・・。なので実際に利用する際には、別途カスタムアクティビティ等を用意してその中で作成してしまうのがいいのかな、と思います。

2011年4月18日月曜日

WorkflowDesigner.Save 実行時に Exception が発生する

リホスティングしているワークフローデザイナーで、デザインした内容を保存する場合には WorkflowDesigner クラスの Save メソッドを呼び出します。しかし、条件ははっきりしていないのですが保存時にぬるぽな Exception が発生する事があります。

これは WF の、というよりも XAML を扱うもの共通で関わる問題なのですが、XAML の解析において正常に解析・解決できないケースがあるということです。その際は XML 名前空間プレフィックスの解決に失敗しインスタンスを生成しようとしたんだけどできなかった、というような形でぬるぽ例外が発生してしまうとのことです。

対応策としては、明示的に「XAML プロセッサで無視してよい」という指定を XAML 上に追加する必要があります。その際に必要となるのが mc:Ignorable 属性です。これを元にWorkflowDesinger.Save 呼び出し時に mc:Ignorable 属性を付与する方法が海外 MSDN Blog に記載されていましたので、それを VB 用に移植したものを紹介します。Blog にて紹介されている IgnorableXamlWrite クラスを用意し、WorkflowDesignerで保存する前に XAML 上に mc:Ignorable 属性を付与するようにします。

  1: Imports System.Collections.Generic
  2: Imports System.IO
  3: Imports System.Xaml
  4: Imports System.Xml
  5: 
  6: Public Class IgnorableXamlXmlWriter
  7:     Inherits XamlXmlWriter
  8: 
  9:     Private ignorableNamespaces As New HashSet(Of NamespaceDeclaration)()
 10:     Private allNamespaces As New HashSet(Of NamespaceDeclaration)()
 11:     Private objectWritten As Boolean
 12:     Private hasDesignNamespace As Boolean
 13:     Private designNamespacePrefix As String
 14: 
 15:     Public Sub New(ByVal tw As TextWriter, ByVal context As XamlSchemaContext)
 16:         MyBase.new(XmlWriter.Create(tw, New XmlWriterSettings With {.Indent = True, .OmitXmlDeclaration = True}),
 17:                                     context,
 18:                                     New XamlXmlWriterSettings With {.AssumeValidInput = True})
 19:     End Sub
 20: 
 21:     Public Overrides Sub WriteNamespace(ByVal namespaceDeclaration As System.Xaml.NamespaceDeclaration)
 22:         If Not objectWritten Then
 23:             allNamespaces.Add(namespaceDeclaration)
 24:             If namespaceDeclaration.Namespace = "http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" Then
 25:                 hasDesignNamespace = True
 26:                 designNamespacePrefix = namespaceDeclaration.Prefix
 27:             End If
 28:         End If
 29:         MyBase.WriteNamespace(namespaceDeclaration)
 30:     End Sub
 31: 
 32:     Public Overrides Sub WriteStartObject(ByVal type As System.Xaml.XamlType)
 33:         If Not objectWritten Then
 34:             If hasDesignNamespace Then
 35:                 Dim mcAlias = "mc"
 36:                 WriteNamespace(New NamespaceDeclaration("http://schemas.openxmlformats.org/markup-compatibility/2006", mcAlias))
 37:             End If
 38:         End If
 39:         MyBase.WriteStartObject(type)
 40: 
 41:         If Not objectWritten Then
 42:             If hasDesignNamespace Then
 43:                 Dim ign As New XamlDirective("http://schemas.openxmlformats.org/markup-compatibility/2006", "Ignorable")
 44:                 WriteStartMember(ign)
 45:                 WriteValue(designNamespacePrefix)
 46:                 WriteEndMember()
 47:                 objectWritten = True
 48:             End If
 49:         End If
 50:     End Sub
 51: 
 52: End Class
 53: 


上記のような形で IgonorableXamlXmlWriter クラスとして用意した次には、このように利用して保存を行います。



  1: Dim mdlTree = designer.Context.Services.GetService(Of Model.ModelTreeManager).Root
  2: Dim sb As New StringBuilder
  3: Dim xsc = New XamlSchemaContext
  4: Dim bw = ActivityXamlServices.CreateBuilderWriter(New IgnorableXamlXmlWriter(
  5:                                                       New StringWriter(sb),
  6:                                                       xsc))
  7: 
  8: XamlServices.Save(bw, mdlTree.GetCurrentValue)
  9: designer.Save("tempWF.xaml")


このようにすることで、WorkflowDesigner が保存を行う際に Ignorable 属性が付与した形で保存されるようになります。流れとしては次のようになります。



その時点でデザイナ上に展開されている内容を取得し、ActivityXamlServices クラスを利用してアクティビティの内容を表すインスタンスを生成します。ActivityXamlServices.CreateBuilderWriter メソッドで生成されたインスタンスに書き込む事ができ、その際に利用する Writer クラスを指定し呼び出します。呼び出す事で、指定した Writer クラスにてアクティビティの XAML を生成する処理が行われますので、その内容を XamlServices.Save メソッドにて保存、WorkflowDesigner 側へと反映させます。その後に WorkflowDesigner.Save メソッドを呼ぶことで、Ignorable 属性が付与した形にてファイルに保存する事ができます。



このように書くと何が何だかわからなくなりそうなので、デザイナから保存する場合はこういうおまじないが必要!、という程度でも構わないですw

2011年4月17日日曜日

第 57 回 CLR/H 勉強会 ~ Oracle デイ~

P4160403

4/16 に行われた第 57 回勉強会のレポートです。今回は Oracle デイと銘打ったこともあり、Oracle を中心に Windows Phone 7 も扱うという内容でした。

セッション 1:Windows Phone 7 はじめました

P4160411

本州より来ていただいた Microsoft MVP であり Oracle ACE な初音( @hatsune_ )さんによるWindows Phone 7 開発についてのセッションです。全般を通して CLR/H 勉強会では非常に珍しく VB メインな話というのは新鮮でした。

つい先日 MIX11 にて発表されたアップデートの話も盛り込みつつ、Windows Phone 7 での開発について基礎から非常にわかりやすい内容だったと思います。開発環境の構築から、導入に当たっての注意点、さらには実際に作成された Hiragana Twit というアプリの実装についてと、60 分枠の中でかなりぎっしり詰まっていて非常に聞き応えもあるセッションでした。

P4160445

Reactive Extensions を用いた実装のところでは、この部分でのデバッグについて話していただいたのですが、1 画面まるまるブレークポイントとなってしまったのには驚きを感じました。匿名関数を利用しているために、1 ステートメント内部に多くの処理が記述されることとなり、デバッグする際には少々注意が必要なのだと思いました。個人的には匿名関数自体を扱いが難しいと感じるところもあり、なおのこと考えさせられます。このあたりは開発に携わる人数やスキルも関わってくるので難しいですね。

P4160448

実機を用いたデバッグについても実際の挙動を見せてもらいました。エディット&コンティニューが利用できないだけで、その他は通常の開発と同様にできるのは便利です。実機を入手するかどうかはさておいて、すでに開発環境が整っている Windows Phone 7。今からでも取り組んでみたいと思わせる、そんな楽しい内容でした。

Lightning Talk

今回のライトニングトークは時間の前後はありましたが 4 名にて行われました。

1: 和風な思ひ出( @naoki0311 さん)

P4160456

CLR/H 代表による LT・・・のようなものです。和風な、というタイトルのあたりで何となく思うところはあるのですが、昨年に行かれた旅行の思い出写真から始まったので確かに和風でした。そして中盤からはわふーでした。なんというかこれが全てです・・・

2: Workflow Foundation…( @twit_ahf )[スライド]

P4160469

ここ最近 WF 熱がまた戻ってきているので勢いに乗ってやってみました。WF は開発者にとってはあまり面白みがないというか IT Pro 向けなところが多いけど、やってみると簡単な AP の制御もできたり色々と出来ることが多いのと、見た目のわかりやすさは比類ないので、是非色々な人に触ってもらいたいと思います。ちなみに、数少ない mixi の開発系コミュニティで存在しないジャンルです・・・

3: WP7 で CLR/H を知ってもらおう( @mentaro さん)

P4160495

そろそろ株式会社 CLR/H 代表取締役社長となってもいいのではないか、と思われる @mentaro さんの LT。今回は Windows Phone 7 でアプリを用意し CLR/H をもっと広く知ってもらおう!、という主題、でいいハズです。そのアプリの凄まじさは何者も寄せ付けません。さすが日本全国にファンがいる @mentaro さん!、と言わざるを得ませんでした。

4: CLR・DLR ( @nobuhisa_k さん)

P4160597

CLR/H スタッフの @nobuhisa_k さんによる「C# で GUI を用意し F# でその機能を実装、さらに IronPython でそれらと対話してみよう!」という LT。さらっと進んでいるのですが、話されている内容はかなり面白いです。コンソールで入力した内容が GUI にそのまま表示される、と思いきやコンソールでロジックを入力して動作させることもできたり、と出来れば今回のソースをどこかで公開してほしいなぁ、と思いました。

おやつタイム

P4160501

今回のおやつはシュークリームやケーキなど!3ついただきました!

セッション 2: プログラマのための ORACLE DBA 入門

P4160504

CLR/H スタッフ @stknohg さんによる Oracle の DBA についての入門セッションです。[スライド]
私自身 Oracle は業務で少々利用したことがあるのですが、最近はそれほどでもなかったのもあり今の Oracle がかなり進化しているのを感じました。イメージとしてはインストールからパラメータ指定して・・・という、初心者お断りなイメージだったのですが今は全然そのような事はなく、基本 OK ボタン連打である程度の環境は構築されるということです。このあたり各 DBMS 製品それぞれ同じような方向性なのかな、と感じました。

P4160547

Oracle の構造や挙動に関係する要素、ファイルシステムやパラメータ、起動・終了時の話題などタイトル通り DBA として必要な部分の基礎を網羅していました。内容もさることながら、非常にスライドが見やすかったのがありがたかったです。

P4160555

バックアップとチューニングに関して最後に重要な点を話されました。非常に同感です。バックアップでいえば、復旧試験をおろそかにしている事が多いのと、案件により異なる復旧までに許される時間により構築内容を考えておく必要がある点など、これから Oracle に限らず DBMS に触れる人にはかなり良い内容であったと思います。残念なのは時間配分が少々失敗したこともあり、後半はかなり駆け足になったことかな・・・。

セッション 3: Oracleでいってみよう!

P4160563

初音( @hatsune_ )さんのもう一つのセッションです。こちらは開発者向けが主体のセッションでした。
Oracle は開発用途であれば無償で利用可能、といきなりショッキングな内容から始まり現在のクエリチューニングの方向性、昔から変化してきた点などこれも驚くことが多かった内容でした。

P4160570

Oracle も SQL Server も ADO.NET を通して利用する際はほとんど違いはなく、SQL-CLR 相当の .NET ストアドも用意されているので、ほとんどどころかほぼ同一の構造になっていました。私は別会社のパッケージカスタマイズでしか .NET + Oracle という環境に触れたことがなかったので、.NET ストアドなど知らない部分が多かったのが驚きです。また昔であれば TNSNAME.ora を書き換えて、といったことも必ず必要であったのですが今はやらなくても構わないとのこと。一番驚いたのはここかも知れませんw

コネクションプーリングについても話されていたのですが、そのあたりで少々問題のある挙動があり問い合わせした件についての話など、面白い話題が随所に盛り込まれていたと感じました。

P4160589

後半では Windows Phone 7 から Oracle にアクセスするための Web サービスを用意し、実際にアクセスしてみるサンプルを見せてもらいました。このあたりを見せてもらうと、今後はスマートフォンを含めWebを利用した開発というのも増えてくるでしょうが、.NETで問題なく端末側からサービス側まで対応できるのだなぁ、と改めて感じます。

講師の方々、参加者の皆さん、Ustで閲覧されていた皆さん、そしてスタッフの皆さん、お疲れさまでした!

2011年4月15日金曜日

Workflow の実行方法

作成した Workflow を実行する方法は3通り用意されています。それぞれに利用シーンがある程度明確にされているので、目的に応じて使い分ける必要があります。

  • WorkflowInvoker:最もシンプルにWorkflowを実行する
  • WorkflowApplication:イベントによる通知や永続化をサポートして実行する
  • WorkflowServiceHost:ワークフローサービスとして外部に公開する

他にも WorkflowInvoker は同一スレッドにて実行されるのと、WorkflowApplication は別スレッドで実行されるという違いはあります。

WorkflowApplication で提供されるイベント(っぽいもの)は次の通りです。

Aborted Action<T> ワークフロー インスタンスが中止されると呼び出される
Completed Action<T> ワークフロー インスタンスが完了すると呼び出される
Idle Action<T> 現在のワークフロー インスタンスがアイドル状態になると呼び出される
OnUnhandledException Func<T, TResult> 現在のワークフロー インスタンスが未処理の例外を検出すると呼び出される
PersistableIdle ActivityFunc 現在のワークフロー インスタンスがアイドル状態になり、永続化できるようになると呼び出される
Unloaded Action<T> 現在のワークフローがアンロードされると呼び出される

これらはイベントとしてではなくプロパティを通して提供されていますので、VB ですので Addressof を利用しメソッドを割り振ります。

  1: Dim wfApps = New System.Activities.WorkflowApplication(wfFile)
  2: wfApps.Completed = AddressOf Completed
  3: wfApps.Run()
  4: 
  5: 
  6: Private Sub Completed(ByVal e As WorkflowApplicationCompletedEventArgs)
  7:     MessageBox.Show("Workflow is Completed!")
  8: End Sub


このような形で組み込むことで、Workflow の状態通知に対して処理を行う事ができるようになります。



WorkflowServiceHost については WCF の知識が必要になります。ただこれもそう難しいところではないと思っていますので、そのうちサンプル等作成してみたいと思います。

2011年4月14日木曜日

Activity のプロパティダイアログで[ファイルを開く]ダイアログの表示

元ネタは海外の BBS から。ファイル名を指定するようなアクティビティを作ろうとした場合、やはり [ファイルを開く] ダイアログを利用して指定させたいというのはあると思います。そのような場合には以下のような感じで実装します。

・DialogPropertyValueEditor を継承したクラスを用意する

  1: Imports System.Activities
  2: Imports System.Activities.Presentation
  3: Imports System.Windows.Forms
  4: 
  5: Public Class FileBrowserDialogPropertyValueEditor
  6:     Inherits PropertyEditing.DialogPropertyValueEditor
  7: 
  8:     Private _res As New ExecuteOtherWorkflowActivityDesigner
  9: 
 10:     Public Sub New()
 11:         Me.InlineEditorTemplate = TryCast(_res.Resources("FileBrowserInlineEditorTemplate"), DataTemplate)
 12:     End Sub
 13: 
 14:     Public Overrides Sub ShowDialog(ByVal propertyValue As System.Activities.Presentation.PropertyEditing.PropertyValue, ByVal commandSource As System.Windows.IInputElement)
 15: 
 16:         Using dlg As New OpenFileDialog
 17:             With dlg
 18:                 .AddExtension = True
 19:                 .CheckFileExists = True
 20:                 .Multiselect = False
 21:                 .Filter = "ワークフロー(*.xaml)|*.xaml|全てのファイル(*.*)|*.*"
 22: 
 23:                 If .ShowDialog = DialogResult.OK Then
 24:                     propertyValue.StringValue = dlg.FileName
 25:                 End If
 26:             End With
 27:         End Using
 28: 
 29:     End Sub
 30: 
 31: End Class


このクラスはプロパティダイアログ上での入力時にどのような挙動をさせるかを記述するクラスとなっています。コンストラクタで、InlineEditorTemplate プロパティに何やら DataTemplate を設定していますが、これがプロパティダイアログ上で表示されるものとなります。今回は面倒だったので、アクティビティで利用するデザイナ上に定義したものを呼び出していますw



  1: <DataTemplate x:Uid="DataTemplate_1" x:Key="FileBrowserInlineEditorTemplate">
  2:     <Border x:Uid="Border_1" BorderThickness ="1">
  3:         <Grid>
  4:             <Grid.ColumnDefinitions>
  5:                 <ColumnDefinition Width="1*"/>
  6:                 <ColumnDefinition Width="Auto"/>
  7:             </Grid.ColumnDefinitions>
  8:             <TextBox Grid.Column="0" Text="{Binding StringValue}"/>
  9:             <sapp:EditModeSwitchButton Grid.Column="1"/>
 10:         </Grid>
 11:     </Border>
 12: </DataTemplate>
 13: 


そのテンプレートの内容はこのような感じにしてあります。テキストボックスはそのままとして EditModeSwitchButton が [...] ボタンの表示を行います。余談ですがこのテンプレートをアクティビティ側に適用した場合、何故か VS によく出てくるピンボタンに変化します。



・アクティビティの対象となるプロパティに Editor 属性を付加する



このように作成したクラスを対象となるプロパティに Editor 属性を利用して設定します。



  1: <Browsable(True)>
  2: <Editor(GetType(FileBrowserDialogPropertyValueEditor), GetType(DialogPropertyValueEditor))>
  3: Public Property WorkflowFile As String


このような感じで設定します。



このように実装したアクティビティを利用するとこのように表示されます。



fileDialog



WorkflowFile プロパティの欄にテキストボックスとボタンが表示されているのが見えると思います。このボタンをクリックすると [ファイルを開く] ダイアログが表示され、そこで選択したファイル名がプロパティの値として設定されるようになります。



このようにアクティビティのプロパティについては、プロパティダイアログ上での入力もカスタマイズできる手段が提供されています。

InvokeMethod アクティビティによるメソッド呼び出し

InvokeMethod アクティビティは、直接メソッドを呼び出し実行する事ができるアクティビティです。極端な事を言えば、これが使えると基本的になんでもできる、と思ってもよいくらいで。ただし少々利用時の設定に癖があります。

Invoke1

今回のサンプルはこのようなワークフローとなります。前半部分では静的クラスのメソッドを呼び出すタイプ、後半は通常のクラスメソッドを呼び出すタイプとなっています。呼び出されるメソッドは次のように作成しました。

  1: Public Class InvokeSample
  2: 
  3:     Public Function TestMethod() As String
  4:         Return "Invoke サンプル用メソッドからの戻りです"
  5:     End Function
  6: 
  7: End Class
  8: 
  9: Public Module InvokeSampleModule
 10: 
 11:     Public Function TestMethod() As String
 12:         Return "Invoke サンプル用メソッドからの戻りです" + ControlChars.NewLine + "これは Shared メソッドです"
 13:     End Function
 14: 
 15: End Module


VB なので静的クラスは Module を利用します。



まず静的クラスメソッドを呼び出す場合は、InvokeMethod アクティビティに次のような設定を行います。




  • TargetType:InvokeSampleModule


  • TargetObject:(設定なし)


  • MethodName:TestMethod



戻り値を受け取る変数は別途定義しておきます。

そして通常クラスのメソッドを呼び出す場合は次のように設定します。




  • TargetType:InvokeSample


  • TargetObject:(設定なし)


  • MethodName:TestMethod



InvokeMethod アクティビティ自体の設定はこのように静的であろうと通常であろうと変わりありません。違いは InvokeMethod アクティビティの前にあります。静的クラスでしたら特に気にしませんが、通常のクラスの場合、あらかじめインスタンス生成を行っておく必要があります。ワークフロー上ではインスタンス生成を直前の Assign アクティビティにて行っています。通常のプログラミングと全く同じことをワークフロー上でも行う形になります。



なお、TargetType プロパティでは「型の参照」を選択する事ができ、別ダイアログにて利用できるクラスを指定する事が出来るようになっています。



invoke3



このようなダイアログです。これ自体も WF で標準提供されている機能だったりします。

2011年4月13日水曜日

Entity Framework と WF

ただの豆知識、にすらならないネタですが。

最近 ADO.NET EntityFramework 4.1 がリリースされたこともあり活気づいていると思います。 EntityFramework を利用すると、非常に簡単にデータをモデルエンティティとして扱えるようになるスゴイものです。

そしてその内部では WF が利用されているというのがわかった、というお話でした。

WF4-1

ここに載せているのは CsdlToSsdlAndMsiActivity と SsdlToDdlActivity の二つ。これらは EntityFramework のモデル作成において内部で利用されているアクティビティです。これでデザイナ周りもリホスティングできれば色々と面白いことができるのですが、残念ながらまだ方法は見つかっていません。

ただこのあたり(モデル生成)については MSDN で一部のクラスが公開されているのと、edmxファイル自体についても結構情報が公開されているので、デザイナを除けば色々とできる事は間違いありません。