坚持学习WF(8):本地服务之调用外部方法

WF提供了一组核心服务,例如在SQL 数据库中存储工作流实例的执行详细信息的持久性服务,计划服务,事务服务和跟踪服务。除了这些WF也提供了另外一种服务,叫做Local Service也可以叫做Data exchange service。主要是实现工作流和宿主程序之间的通信,使工作流能够使用方法和事件通过消息与外部系统交互。 事件用于将数据发送到工作流,而工作流使用方法将数据发送到主机应用程序。 通过事件与工作流进行通信的功能提供了一种将数据发送到工作流的异步方式。本文主要讲述调用外部方法的部分。

下图说明本地通信服务如何与其主机应用程序通信:

01

下面首先说说如何开发一个本地服务:

1.使用C#的接口定义服务契约,在接口中定义你方法和事件。并使用[ExternalDataExchangeAttribute]装饰该接口,用于说明这是一个本地服务的接口。 
2.开发一个实现了该接口的类,用于实现你的逻辑。 
3.创建一个工作流实例,并将该本地服务添加到工作流引擎中去。

我们开发一个简单的本地服务的例子,根据AccountID来修改Balance的值,并使用三种方式来调用: 
1.定义一个Account类,代码如下(Account.cs)

using System; 
namespace CaryWorkflows 

    [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属性,代码如下(IAccountServices.cs):

using System;
using System.Workflow.Activities;
namespace CaryWorkflows 
{[ExternalDataExchange]public interface IAccountServices{Account AdjustBalance(Int32 id, Double adjustment);}
}

3.实现该接口,代码如下():

using System;
using System.Collections.Generic;
namespace CaryWorkflows 
{public 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;}       }
}
 
服务定义好了,我们下面就要在工作流中条用该服务,我们有三种方式:


在工作流中定义三个属性:
using System;
using System.Workflow.Activities;
namespace CaryWorkflows 
{public sealed partial class BalanceAdjustmentWorkflow: 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; }}public BalanceAdjustmentWorkflow(){InitializeComponent();}}
}
 
然后我们向工作流中拖入一个CodeActivity,Activity有一个方法OnActivityExecutionContextLoad(),我们通过该
的IServiceProvider的GetService方法来获取本地服务,代码如下:
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");}
}
 
在CodeActivity的ExecuteCode事件中调用本地服务的方法,代码如下:
 
private void codeAdjustAccount_ExecuteCode(object sender, EventArgs e)
{Account = _accountServices.AdjustBalance(Id, Adjustment);
}
 
最后要将该服务添加到工作流引擎当中去,
1. 先将ExternalDataExchangeService服务对象添加到引擎。
2.再将我们自己开发的服务绑定到ExternalDataExchangeService服务中。
宿主程序的代码如下:
using System;
using System.Collections.Generic;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using CaryWorkflows ;
namespace ConsoleLocalServices
{public class LocalServiceTest{public static void Run(){using (WorkflowRuntimeManager manager= new WorkflowRuntimeManager(new WorkflowRuntime())){AddServices(manager.WorkflowRuntime);manager.WorkflowRuntime.StartRuntime();                Dictionary<String, Object> wfArguments= new Dictionary<string, object>();              Console.WriteLine("开始....");wfArguments.Add("Id", 101);wfArguments.Add("Adjustment", -25.00);WorkflowInstanceWrapper instance = manager.StartWorkflow(
typeof(CaryWorkflows.BalanceAdjustmentWorkflow), wfArguments);manager.WaitAll(2000);Account account = instance.OutputParameters["Account"] as Account;if (account != null){Console.WriteLine( "Revised Account: {0}, Name={1}, Bal={2:C}",account.Id,
account.Name, account.Balance);}else{Console.WriteLine("Invalid Account Id\n\r");}Console.WriteLine("结束....");}} private static void AddServices(WorkflowRuntime instance){ExternalDataExchangeService exchangeService = new ExternalDataExchangeService();instance.AddService(exchangeService); exchangeService.AddService(new AccountService());}} }
这样我们使用代码方式调用外部方法就结束了,结果如下:
 
 
 
1.添加一个app.config到项目中,代码如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration><configSections><section name="WorkflowRuntime" type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,PublicKeyToken=31bf3856ad364e35" /><section name="LocalServices" type="System.Workflow.Activities.ExternalDataExchangeServiceSection, System.Workflow.Activities, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/></configSections><WorkflowRuntime Name="ConsoleLocalServices" ><CommonParameters><!--Add parameters common to all services--></CommonParameters><Services><!--Add core services here--></Services></WorkflowRuntime><LocalServices ><Services><!--Add local services here--><add type="CaryWorkflows.AccountService, CaryWorkflows,Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" /></Services></LocalServices >
</configuration>
2.我们只要需改动宿主程序中如下部分: 
using (WorkflowRuntimeManager manager= new WorkflowRuntimeManager(new 
WorkflowRuntime("WorkflowRuntime"))); ExternalDataExchangeService exchangeService = new ExternalDataExchangeService("LocalServices");
 

1.首先自定义一个活动(AdjustAccountActivity.cs), 我们在自定义活动中获取本地服务,并且调用其中方法,代码如下:
using System;
using System.ComponentModel;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;
namespace CaryWorkflows 
{public partial class AdjustAccountActivity : Activity{public static DependencyProperty IdProperty= System.Workflow.ComponentModel
.DependencyProperty.Register("Id", typeof(Int32), typeof(AdjustAccountActivity));[Description("Identifies the account")][Category("Local Services")][Browsable(true)][DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]public Int32 Id{get{return ((Int32)(base.GetValue(AdjustAccountActivity.IdProperty)));}set{base.SetValue(AdjustAccountActivity.IdProperty, value);}}public static DependencyProperty AdjustmentProperty = System.Workflow.ComponentModel.
DependencyProperty.Register("Adjustment", typeof(Double), typeof(AdjustAccountActivity));[Description("The adjustment amount")][Category("Local Services")][Browsable(true)][DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]public Double Adjustment{get{return ((Double)(base.GetValue(AdjustAccountActivity.AdjustmentProperty)));}set{base.SetValue(AdjustAccountActivity.AdjustmentProperty, value);}}public static DependencyProperty AccountProperty= System.Workflow.ComponentModel.
DependencyProperty.Register("Account", typeof(Account), typeof(AdjustAccountActivity));[Description("The revised Account object")][Category("Local Services")][Browsable(true)][DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]public Account Account{get{return ((Account)(base.GetValue( AdjustAccountActivity.AccountProperty)));}set{base.SetValue(AdjustAccountActivity.AccountProperty, value);}}public AdjustAccountActivity(){InitializeComponent();}protected override ActivityExecutionStatus Execute( ActivityExecutionContext
executionContext){IAccountServices accountServices =executionContext.GetService<IAccountServices>();if (accountServices == null){throw new InvalidOperationException( "fail IAccountServices from runtime");}Account = accountServices.AdjustBalance(Id, Adjustment);return base.Execute(executionContext);}} }
2.在工作流中我们将该自定义活动拖到工作流中,并设置相应的属性即可。
 
 
使用该方式我们只需要拖一个CallExternalMethodActivity到工作流中,并且设置起相应属性即可,如下图:
这三种方式的执行结果都是一样的。
上一篇:坚持学习WF(7):流程控制(Flow Control)

下一篇:坚持学习WF(9):本地服务之事件处理



本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2008/05/09/CallExternalMethod.html,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/396958.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++归并排序_合并排序法

一、合并排序(Merge Sort) 就是将多个有序数据表合并成一个有序数据表。如果参与合并的只有两个有序表&#xff0c;那么称为二路合并。对于一个原始的待排序序列&#xff0c;往往可以通过分割的方法来归结为多路合并排序。二、一个待排序的原始数据序列进行合并排序的基本思路是…

微习惯虽好,但是最重要的还是坚持

2019独角兽企业重金招聘Python工程师标准>>> “微习惯”一词是由美国的斯蒂芬盖斯提出的。他以前是个宅男&#xff0c;懒虫&#xff0c;为了改变自己而找到了这个方法。并且在自己身上实验成功。养成了好的读书、写作和健身的习惯&#xff0c;实现了人生的华丽转身。…

带你了解zabbix整合ELK收集系统异常日志触发告警~

今天来了解一下关于ELK的“L”-Logstash,没错&#xff0c;就是这个神奇小组件&#xff0c;我们都知道&#xff0c;它是ELK不可缺少的组件&#xff0c;完成了输入&#xff08;input&#xff09;&#xff0c;过滤&#xff08;fileter&#xff09;&#xff0c;output&#xff08;输…

用python设计学生管理系统_Python实现GUI学生信息管理系统

本文实例为大家分享了Python实现GUI学生信息管理系统的具体代码&#xff0c;供大家参考&#xff0c;具体内容如下 项目环境&#xff1a; 软件环境: OS:RedHat6.3 Lib:Pygtk Language:Python Support tool:Glade3 项目简述&#xff1a; ①Glade3设计用户的登录窗口&#xff0c;功…

python理论知识选择题_Python基础自测题答案和基础知识梳理

Python基础自测题答案和基础知识梳理 1.关于Python中的lambda表达式的函数体自能是单独一条语句&#xff0c;所以答案选择C。 例如&#xff1a;>>>g lambda x: 2*x1 g(3) 7 2.Python中的变量不需要事先声明&#xff0c;但是需要创建和赋值&#xff0c;否则你怎么用&a…

查找算法之顺序查找

参考&#xff1a; 1. 顺序查找 | 博客园 基本思想&#xff1a; 顺序查找&#xff0c;就是从第一个元素开始&#xff0c;按索引顺序遍历待查找序列&#xff0c;直到找出给定目标或者查找失败。 特点&#xff1a; 1. 对待查序列&#xff08;表&#xff09;无要求 -- 待查找序列可…

python数据预测_python时间序列预测股票走势

提示&#xff1a;这只是个训练模型&#xff0c;技术不具备实际意义&#xff0c;入市需谨慎。 首先调用tushare包 import tushare as ts import pandas as pd import matplotlib.pyplot as plt 查自己比较感兴趣的股票&#xff0c;这里我查找的是新能源/燃料电池/氢燃料&#xf…

30.Android之百度地图简单学习

今天用了下百度地图&#xff0c;简单写了一个例子&#xff0c;记录下。 一、申请AK&#xff08;API Key&#xff09; 要想使用百度地图sdk&#xff0c;就必须申请一个百度地图的api key。申请流程挺简单的。 首先注册成为百度的开发者&#xff0c;然后打开http://lbsyun.baidu.…

python爬取b站弹幕_爬取B站弹幕并且制作词云

目录 SRE实战 互联网时代守护先锋&#xff0c;助力企业售后服务体系运筹帷幄&#xff01;一键直达领取阿里云限量特价优惠。 爬取弹幕 1. 从手机端口进入网页爬取找到接口 2.代码 import requests from lxml import etree import numpy as np urlhttps://api.bilibili.com/x/v1…

python控制灯_Python 控制树莓派 GPIO 输出:控制 LED 灯

树莓派 GPIO 控制输出的入门应该都是从控制 LED 灯开始的吧。 树莓派版本&#xff1a;Model 3B 树莓派系统&#xff1a;Raspbian Stretch with desktop and recommended software&#xff0c;April 2019 连接装置 准备一个 LED 灯&#xff0c;两个两头都为母的杜邦线。对照下图…

报错型sql注入原理分析

0x00&#xff1a;前言关于sql注入&#xff0c;经久不衰&#xff0c;现在的网站一般对sql注入的防护也相对加强了&#xff0c;2016年的***测试报告中&#xff0c;出现最多的是xss&#xff08;跨站脚本***&#xff09;和明文传输等&#xff0c;但是对sql注入的利用方式&#xff0…

matlab矩阵 0,matlab zeros初始化为0矩阵

zeros为创建一个值为零的数组&#xff1b;如matrix1zeros(4,5);%4*5的矩阵&#xff0c;矩阵中每个元素都为0matrix2zeros(4,5,3);%4*5*3的数组&#xff0c;数组中每个元素都为0下面举一个将图像存到数组的例子对RGB图片1.jpg&#xff0c;2.jpg&#xff1b;大小为700*500*3创建4…

批处理命令Start

2019独角兽企业重金招聘Python工程师标准>>> 运行hello.exe&#xff08;最小化&#xff09; start /MIN hello.exe 用记事本打开readme.txt&#xff08;最大化&#xff09; start /MAX notepad readme.txt 打开网页 start http://www.baidu.com/ 调用另外一个脚本&…

arcgis python实例_arcgis二次开发_arcgis二次开发python_arcgis二次开发实例

[1.rar] - QQ连连看的源码.单消秒杀挂机等功能喜欢的朋友请拿去研究 [qqCHAR.rar] - qq 验证码识别程序 可以叫准确的识别出qq登陆前的验证码 [1.rar] - 本书以Visualc作为开发语言&#xff0c;结合大量实例&#xff0c;详细介绍了利用Arcobjects组件进行GIS二次开发的方法和过…

Linux命令-自动挂载文件/etc/fstab功能详解

一、/etc/fstab文件的作用磁盘被手动挂载之后都必须把挂载信息写入/etc/fstab这个文件中&#xff0c;否则下次开机启动时仍然需要重新挂载。系统开机时会主动读取/etc/fstab这个文件中的内容&#xff0c;根据文件里面的配置挂载磁盘。这样我们只需要将磁盘的挂载信息写入这个文…

一、在windows环境下修改pip镜像源的方法(以python3为例)

在windows环境下修改pip镜像源的方法(以python3为例) 1.在windows文件管理器中,输入 %APPDATA% 2.会定位到一个新的目录下&#xff0c;在该目录下新建pip文件夹&#xff0c;然后到pip文件夹里面去新建个pip.ini文件 3.在新建的pip.ini文件中输入以下内容&#xff0c;搞定 [glob…

得到选择框句柄 怎么操作_电脑版微信怎么多开?最简单的三种电脑版微信多开教程...

​在现实中的我们在网络上却又很多张脸&#xff0c;多开微信很多人都是需要的&#xff0c;这里就介绍3个方法给大家多开。方法1&#xff1a;BAT文件鼠标右键单击微信图标选择 属性在属性选项夹内复制 “目标”例如我的是("D:Program Files (x86)TencentWeChatWeChat.exe&q…

macos sierra 引导镜像_真想不到,在win10上可以制作苹果macOS启动U盘

不管你使用的是macOS还是Windows10&#xff0c;电脑出现启动问题是很正常的&#xff0c;原因有很多种&#xff0c;包括(但不限于)文件损坏、硬件故障和错误更新等。如果意外发生在苹果电脑上&#xff0c;可以使用带有安装文件的macOS启动U盘来修复它。这正是在电脑正常工作时应…

python(1) - 数据类型和变量

数据类型&#xff1a; 整数&#xff1a;就是整数&#xff0c;包括正整数&#xff0c;0&#xff0c;负整数 浮点数&#xff1a; 通俗点说&#xff0c;就是小数 长整数&#xff1a; 就是比较长的整型&#xff0c;通常后面会跟一个L 字符串&#xff1a; 字符串需要用“”或’’括起…

powershell awk_谈谈 PowerShell

万事万物&#xff0c;有始有终。直从萌芽拔&#xff0c;高自毫末始。所谓的 Shell&#xff0c;无非是应用程序与操作系统内核进行交互的一个中间程序而已。我本人玩电脑也有很久一阵子了&#xff0c;最开始接触到的就是Windows 7 操作系统&#xff0c;当时 Windows 7 上市不久&…