惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

P
Palo Alto Networks Blog
P
Proofpoint News Feed
GbyAI
GbyAI
Microsoft Azure Blog
Microsoft Azure Blog
B
Blog
Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
Recorded Future
Recorded Future
M
MIT News - Artificial intelligence
罗磊的独立博客
J
Java Code Geeks
月光博客
月光博客
F
Full Disclosure
博客园 - 聂微东
人人都是产品经理
人人都是产品经理
U
Unit 42
WordPress大学
WordPress大学
A
About on SuperTechFans
C
Cyber Attacks, Cyber Crime and Cyber Security
SecWiki News
SecWiki News
Security Latest
Security Latest
C
Check Point Blog
C
CERT Recently Published Vulnerability Notes
小众软件
小众软件
I
InfoQ
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
B
Blog RSS Feed
V
Visual Studio Blog
博客园_首页
NISL@THU
NISL@THU
I
Intezer
Spread Privacy
Spread Privacy
AWS News Blog
AWS News Blog
The Register - Security
The Register - Security
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Latest news
Latest news
Project Zero
Project Zero
博客园 - 叶小钗
C
Cybersecurity and Infrastructure Security Agency CISA
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Privacy International News Feed
博客园 - 【当耐特】
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threat Research - Cisco Blogs
Simon Willison's Weblog
Simon Willison's Weblog
T
Tor Project blog
V
Vulnerabilities – Threatpost
博客园 - 司徒正美
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
雷峰网
雷峰网

博客园 - gotolovo

导出csv 导出excel 正则学习电话匹配 logmanager des 加密 解密 - gotolovo c# 发送邮件 工作流学习过程-事务 工作流学习过程-状态机 蛋疼的viewstate 工作流学习过程-持久化服务 工作流学习过程-使用关联 工作流学习过程-本地服务之事件处理 工作流学习过程-验证活动 工作流学习过程-自定义活动 工作流学习过程-开篇 基本的几个排序算法 关于sql中时间的格式转换 数据行变列 请编程遍历页面上所有TextBox控件并给它赋值为空
工作流学习过程-本地服务之调用方法
gotolovo · 2010-10-25 · via 博客园 - gotolovo

先来看看工作流如何调用服务
基础代码如下:

一个实体类用于传递参数

代码

public class Account
{
public int AccountId { get; set; }
public double AcccountAmount { get; set; }
public double AccountBalance { get; set; }public override string ToString()
{
return string.Format("AccountId:{0}\tAcccountAmount:{1}",AccountId.ToString(),AcccountAmount.ToString());
}
}

接口及服务代码:

代码

public interface ILocalService
{
Account Calculator(Account Account);
}
public class LocalService:ILocalService
{
#region ILocalService 成员public Account Calculator(Account account)
{
return innerCalculator(account);
}
#endregionprivate Account innerCalculator(Account account)
{
account.AcccountAmount
= account.AcccountAmount + account.AccountBalance;
Console.WriteLine(account);
return account;
}
}

新建一工作流
定义两个绑定属性分别为接受和返回的
加一个CodeActivity事件为codeActivity1_ExecuteCode

具体代码如下:

代码

public sealed partial class LocalServiceActivity : SequentialWorkflowActivity
{
public static DependencyProperty LocalServiceValueProperty = DependencyProperty.Register("LocalServiceValue", typeof(Account), typeof(LocalServiceActivity));

[DescriptionAttribute(

"LocalServiceValue")]
[CategoryAttribute(
"LocalServiceValue Category")]
[BrowsableAttribute(
true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public Account InputValue
{
get
{
return ((Account)(base.GetValue(LocalServiceActivity.LocalServiceValueProperty)));
}
set
{
base.SetValue(LocalServiceActivity.LocalServiceValueProperty, value);
}
}
public static DependencyProperty OutputValueProperty = DependencyProperty.Register("OutputValue", typeof(Account), typeof(LocalServiceActivity));

[DescriptionAttribute(

"OutputValue")]
[CategoryAttribute(
"OutputValue Category")]
[BrowsableAttribute(
true)]
[DesignerSerializationVisibilityAttribute(DesignerSerializationVisibility.Visible)]
public Account OutputValue
{
get
{
return ((Account)(base.GetValue(LocalServiceActivity.OutputValueProperty)));
}
set
{
base.SetValue(LocalServiceActivity.OutputValueProperty, value);
}
}
public LocalServiceActivity()
{
InitializeComponent();
}
private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
ILocalService service
= new LocalService();
OutputValue
= service.Calculator(InputValue);
}
}

新建宿主程序。执行代码

代码

private static void LocalServiceTest1()
{
BaseWorkflow.Loaclservice.Account outaccount
= new BaseWorkflow.Loaclservice.Account();using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle
= new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted
+= delegate(object sender, WorkflowCompletedEventArgs e) {
outaccount
= (BaseWorkflow.Loaclservice.Account)(e.OutputParameters["OutputValue"]);
waitHandle.Set(); };
workflowRuntime.WorkflowTerminated
+= delegate(object sender, WorkflowTerminatedEventArgs e) { waitHandle.Set(); };

Dictionary

<string, object> paras = new Dictionary<string, object>();

BaseWorkflow.Loaclservice.Account account

= new BaseWorkflow.Loaclservice.Account() { AccountId = 1001, AcccountAmount = 200,AccountBalance=50 };

paras.Add(

"InputValue", account);

WorkflowInstance instance;
instance

= workflowRuntime.CreateWorkflow(typeof(LocalServiceActivity), paras);
instance.Start();
waitHandle.WaitOne();

Console.Write(outaccount);

Console.ReadKey();
}
}

运行可观察到 服务确实被工作流调用了。而且最后结果也可以返回给宿主
那么本地服务是什么呢?
WF提供了一种服务,叫做Local Service也可以叫做Data exchange service。主要是实现工作流和宿主程序之间的通信,使工作流能够使用方法和事件通过消息与外部系统交互。 事件用于将数据发送到工作流,而工作流使用方法将数据发送到主机应用程序。 通过事件与工作流进行通信的功能提供了一种将数据发送到工作流的异步方式。
下面首先说说如何开发一个本地服务:
1.使用C#的接口定义服务契约,在接口中定义你方法和事件。并使用[ExternalDataExchangeAttribute]装饰该接口,用于说明这是一个本地服务的接口。
2.开发一个实现了该接口的类,用于实现你的逻辑。

3.创建一个工作流实例,并将该本地服务添加到工作流引擎中去:实现方法

ExternalDataExchangeService dataservice = new ExternalDataExchangeService();
workflowRuntime.AddService(dataservice);
YourService yourService
= new YourService();
dataservice.AddService(yourService);

1). 先将ExternalDataExchangeService服务对象添加到引擎。
2).再将我们自己开发的服务绑定到ExternalDataExchangeService服务中。接口具体代码

[ExternalDataExchange]
public interface ILocalService
{
Account Calculator(Account Account);
}
服务代码
public class LocalService:ILocalService
{
#region ILocalService 成员public Account Calculator(Account account)
{
return innerCalculator(account);
}
#endregionprivate Account innerCalculator(Account account)
{
account.AcccountAmount
= account.AcccountAmount + account.AccountBalance;
Console.WriteLine(account);
return account;
}
}

宿主代码

代码

private static void LocalServiceTest2()
{
BaseWorkflow.Loaclservice.Account outaccount
= new BaseWorkflow.Loaclservice.Account();using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle
= new AutoResetEvent(false);

ExternalDataExchangeService dataservice

= new ExternalDataExchangeService();
workflowRuntime.AddService(dataservice);
LocalService accountService
= new LocalService();
dataservice.AddService(accountService);

workflowRuntime.WorkflowCompleted

+= delegate(object sender, WorkflowCompletedEventArgs e)
{
outaccount
= (BaseWorkflow.Loaclservice.Account)(e.OutputParameters["OutputValue"]);
waitHandle.Set();
};
workflowRuntime.WorkflowTerminated
+= delegate(object sender, WorkflowTerminatedEventArgs e) { waitHandle.Set(); };

Dictionary

<string, object> paras = new Dictionary<string, object>();

BaseWorkflow.Loaclservice.Account account

= new BaseWorkflow.Loaclservice.Account() { AccountId = 1001, AcccountAmount = 200, AccountBalance = 50 };

paras.Add(

"InputValue", account);

WorkflowInstance instance;
instance

= workflowRuntime.CreateWorkflow(typeof(LocalServiceActivity), paras);
instance.Start();
waitHandle.WaitOne();

Console.Write(outaccount);

Console.ReadKey();
}
}


服务定义好了,我们下面就要在工作流中条用该服务,我们有几种方式:
方法一:
Activity有一个方法OnActivityExecutionContextLoad(),我们通过该

的IServiceProvider的GetService方法来获取本地服务,代码如下:

代码

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


OnActivityExecutionContextLoad 表示活动正加载到工作流运行时

方法二:配置文件方式
方法三:使用自定义活动 

代码

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
service
= executionContext.GetService(typeof(ILocalService)) as ILocalService;
if (service == null)
{
throw new InvalidOperationException("Unable to retrieve ILocalService from runtime");
}
OutputValue
=service.Calculator(InputValue);
return base.Execute(executionContext);
}

方法四:使用CallExternalMethodActivity
interfaceType为接口名称,MethodName为调用的方法名称,该方法如何有参数则属性窗口中将会列出以供选择,返回值亦是如此,
需要指出的是。这种情况下。参数类型必须为可序列化的
其它情况不是也可以的~