坚持学习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;往往可以通过分割的方法来归结为多路合并排序。二、一个待排序的原始数据序列进行合并排序的基本思路是…

golang json数组拼接

2016年06月16日 15:38:25 阅读数&#xff1a;2575 标签&#xff1a; golang json 数组 更多 个人分类&#xff1a; golang func main() {a : []byte({"Parents": [ "aaaaa", "bbbbbbb" ]})b : []byte({"Parents": [ "Gomez"…

php课程设计实验心得,PHP程序设计教程实验及课程设计

部分 教程1 基础教程1.1 简介1.2 WampServer安装1.3 PHP语法1.4 变量1.5 echo和print语句1.6 数据类型1.7 字符串函数1.8 常量1.9 运算符1.10 条件语句1.11 Switch语句1.12 循环语句1.13 函数部分 教程1 基础教程1.1 简介1.2 WampServer安装1.3 PHP语法1.4 变量1.5 echo和print…

DRUID连接池的简单使用

DRUID——为监控而生的DB池 1. DRUID介绍 DRUID是阿里巴巴开源平台上一个数据库连接池实现&#xff0c;它结合了C3P0、DBCP、PROXOOL等DB池的优点&#xff0c;同时加入了日志监控&#xff0c;可以很好的监控DB池连接和SQL的执行情况&#xff0c;可以说是针对监控而生的DB连接池…

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

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

php手机端多图预览上传,JS实现多图预览上传的实例代码

这篇文章主要介绍了JS实现多张图片预览同步上传功能的相关资料,需要的朋友可以参考下废话不多说了&#xff0c;直接给大家贴代码了&#xff0c;具体代码如下所示&#xff1a;/*** Created by liujing on 2017/5/10.*/$(document).ready(function($) {function changef(which,bu…

带你了解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;功…

http响应头设置

protected void service(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置响应头数据response.setHeader(null, "HTTP/1.1 200 OK");response.setHeader("Server", "Apache-Coyote/1.1"…

java用数组实现单词计数,MapReduce实现单词计数原理及Java编程:WordCount

MapReduce实现单词计数&#xff1a;WordCount单词计数的文本信息(hello.txt)&#xff1a;hello can i help youi have a dreammaybe you can help me​ 实现过程&#xff1a;​ Map过程&#xff1a;并行读取文本&#xff0c;对读取的单词进行Map操作&#xff0c;每个词将会形成…

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

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

STM32f4 ARM Bootloader

参考资料&#xff1a; 基于ARM 的嵌入式系统Bootloader 启动流程分析 Bootloader 详解 ( 代码环境 | ARM 启动流程 | uboot 工作流程 | 架构设计) Android系统启动流程 -- bootloader 在main()之前&#xff0c;IAR都做了啥&#xff1f; STM32 IAP程序 源码 和测试代码 有详细的…

查找算法之顺序查找

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

matlab kfda,SVD与KFDA相结合人脸识别-matlab-毕业论文

XXXXxx毕业设计(论文)最高达到88%。当在抽取的特征维数为39&#xff0c;PCA空间的投影维数为110的情况下&#xff0c;随着训练样本个数的增加&#xff0c;LDA的识别情况如表4所示表4 ORL人脸库LDA测试结果(2)训练样本数 识别率/% 识别时间/S3 68.2 52.3594 87.92 31.5315 88.00…

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.…

在datatable中,在指定位置插入列

假如dataset ds 里面已经存在了数据&#xff0c;当我们想在datatable中插入一列数据&#xff0c;可以用以下方法实现&#xff1a;ds.Tables[0].Columns.Add("star");ds.Tables[0].Columns["star"].SetOrdinal(0);这样“star”列就添加到datatable的第一列了…

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

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

myeclipse始终build workspace

之前我的myeclipse运行某个项目的时候&#xff0c;总是不停的buildworkspace&#xff0c;而且稍微改动一个(不管是java类还是jsp)都会加载接近1分钟甚至更久&#xff0c;从网上搜了好久&#xff0c;先总结下搜的多数方法 1、叫你去掉.project文件的一段话 <buildCommand>…