ワークフローとホストアプリケーションのコミュニケーション


WFは、ワークフローインスタンスの実行詳細をSQLデータベースに格納する永続性サービス、計画サービス、トランザクションサービス、追跡サービスなどのコアサービスのセットを提供します.これらのWFに加えて、Local ServiceともData exchange serviceとも呼ばれる別のサービスも提供されています.主にワークフローとホストプログラム間の通信を実現し、ワークフローが方法とイベントを使用してメッセージを通じて外部システムと対話できるようにする.イベントはワークフローにデータを送信するために使用され、ワークフローはホストアプリケーションにデータを送信する方法を使用します.イベントを介してワークフローと通信する機能は、ワークフローにデータを送信する非同期方式を提供する.本稿では,外部メソッドを呼び出す部分について述べる.
まず、ローカルサービスを開発する方法について説明します.
1.C#のインタフェースを使用してサービス契約を定義し、インタフェースでメソッドとイベントを定義します.[ExternalDataExchangeAttribute]を使用してインタフェースを装飾し、ローカルサービスのインタフェースであることを説明します.
2.このインタフェースを実現したクラスを開発し、あなたの論理を実現します.
3.ワークフローインスタンスを作成し、ローカル・サービスをワークフロー・エンジンに追加します.
1.Accountクラスの定義

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WorkflowConsoleApplication5
{
    [Serializable]
	public class Account
	{
        private Int32 _id;
        private String _name = String.Empty;
        private Double _balance;

        public Int32 Id
        {
            get { return _id; }
            set { _id = value; }
        }

        public String Name
        {
            get { return _name; }
            set { _name = value; }
        }

        public Double Balance
        {
            get { return _balance; }
            set { _balance = value; }
        }
	}
}


2.ExternalDataExchangeプロパティが必要なインタフェースを定義します.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;
namespace WorkflowConsoleApplication5
{
    [ExternalDataExchange]
	interface IAccountServices
	{
        Account AdjustBalance(Int32 id, Double adjustment);
	}
}

3.インタフェースの実装

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WorkflowConsoleApplication5
{
	class AccountService:IAccountServices
	{
        private Dictionary<Int32, Account> _accounts= new Dictionary<int, Account>();
        public AccountService()
        {
            Account account = new Account();
            account.Id = 101;
            account.Name = "Neil Armstrong";
            account.Balance = 100.00;
            _accounts.Add(account.Id, account);
        }
       public Account AdjustBalance(Int32 id, Double adjustment)
        {
            Account account = null;
            if (_accounts.ContainsKey(id))
            {
                account = _accounts[id];
                account.Balance += adjustment;
            }
            return account;
        }       
    }
}

コード方式
ワークフローで3つのプロパティを定義します.
ワークフローにCodeActivityをドラッグします.Activityには、IServiceProviderのGetServiceメソッドを使用してローカルサービスを取得する方法があります.
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;

namespace WorkflowConsoleApplication5
{
    public sealed partial class Workflow1 : SequentialWorkflowActivity
    {
        private Int32 _id;
        private Double _adjustment;
        private Account _account;
        private IAccountServices _accountServices;

        public Int32 Id
        {
            get { return _id; }
            set { _id = value; }
        }
        public Double Adjustment
        {
            get { return _adjustment; }
            set { _adjustment = value; }
        }
        public Account Account
        {
            get { return _account; }
            set { _account = value; }
        }

        protected override void OnActivityExecutionContextLoad(IServiceProvider provider)
        {
            base.OnActivityExecutionContextLoad(provider);
            _accountServices = provider.GetService(typeof(IAccountServices)) as IAccountServices;
            if (_accountServices == null)
            {
                throw new InvalidOperationException("Unable to retrieve IAccountServices from runtime");
            }
        }
        public Workflow1()
        {
            InitializeComponent();
        }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Account = _accountServices.AdjustBalance(Id, Adjustment);
            System.Console.WriteLine(Id+"    "+Adjustment);
        }
    }

}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using System.Workflow.Activities;
namespace WorkflowConsoleApplication5
{
    class Program
    {
        static void Main(string[] args)
        {
            using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
            {
                AutoResetEvent waitHandle = new AutoResetEvent(false);

                ExternalDataExchangeService dataservice = new ExternalDataExchangeService();
                workflowRuntime.AddService(dataservice);
                AccountService accountService = new AccountService();
                dataservice.AddService(accountService);                Dictionary<String, Object> dic = new Dictionary<string, object>();
                dic.Add("Id",2);
                dic.Add("Adjustment",23.25);
                workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
                workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
                {
                    Console.WriteLine(e.Exception.Message);
                    waitHandle.Set();
                };

                WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowConsoleApplication5.Workflow1),dic);
                instance.Start();

                waitHandle.WaitOne();
            }
        }
    }
}