VSWF4 学习笔记.docx
《VSWF4 学习笔记.docx》由会员分享,可在线阅读,更多相关《VSWF4 学习笔记.docx(21页珍藏版)》请在冰豆网上搜索。
VSWF4学习笔记
VS2010学习笔记WF4
(1)第一个Workflow程序:
HelloWorkflow
1.创建HelloWorkflow4程序
2.任务一创建简单的HelloWorkflow程序
1.学习时间
2.演示步骤
3.验证
到了澳洲之后,一边找工作一边开始学习VS2010,正好新的宽带装好,到网上下载了VS2010RC,跟着VS2010TrainingKit一步步学习微软最新的开发工具。
由于一直对工作流比较感兴趣,所以就先从WF开始。
Workflow在VS2010中,被称为WF4,对应着.NETFramework4的版本。
先提供几个资源的下载地址:
VisualStudio2010UltimateRC
VisualStudio2010and.NETFrameworkTrainingKit
10-4ShowinChannel9(每周一个视频,介绍VS2010和.NETFramework4.0)
创建HelloWorkflow4程序
任务一创建简单的HelloWorkflow程序
从Console输出“HelloWorkflow4”的消息,类似以下代码的执行结果:
privatestaticvoidSayHello()
{
Console.WriteLine("HelloWorkflow4");
}
学习时间
5分钟
演示步骤
1.运行VS2010RC
2.创建HellowWorkflow项目
o从菜单File/NewProject...
oNewProject窗口中,左边模板中选择VisualC#-->Workflow,选择WorkflowConsoleApplication
o在名称中输入HelloWorkflow
o选择Createdirctoryforsolution复选框
o按OK确定
3.VS2010会在工作流设计器中打开默认的Workflow1.xaml文件
4.从工具栏Primitives页选中WriteLineactivity并拖动到设计器中央Dragactivityhere提示处
5.选中WriteLine,并通过属性窗口或者直接输入Text属性:
"HelloWorkflow4",注意,字符串表达式一定用双引号括起来
验证
1.按CTRL+F5运行项目
2.在控制台输出窗口,会得到以下结果:
HelloWorkflow4
Pressanykeytocontinue...
VS2010学习笔记WF4
(2)修改默认名称
1.任务一修改默认名称Workflow1为SayHello
2.学习时间
1.步骤
2.任务二修改程序启动的Main方法
3.学习时间
4.步骤
5.验证
通过上一个学习,已经创建了第一个Workflow程序,可VS2010帮忙创建的工作流Workflow1并不是一个很好的名字,表达性不高,所以这一次学习如何将默认的名称改为我们需要的工作流名称SayHello。
任务一修改默认名称Workflow1为SayHello
学习时间
2分钟
步骤
1.运行VS2010,并打开创建好的HelloWorflow项目
2.在SolutionExplorer中选择Workflow1.xaml
3.通过F2或者快捷菜单选择Rename,将之修改为SayHello.xaml
1.注意:
VS2010在你修改别的类文件(.cs)时,会询问并自动将类名改为对应的文件名,但对于XAML文件,VS不会帮你这么做,因此需要继续完成以下4~5步
4.双击在设计器打开SayHello.xaml
5.点击设计器空白处(不要选择任何activity)
6.在属性窗口,将Name从HelloWorkflow.Workflow1修改为HelloWorkflow.SayHello
7.按CTRL+SHIFT+B编译项目
8.编译出现错误:
提示找不到类型或命名空间Workflow1,因为我们修改了工作流的名称。
SayHellow工作流实际上继承于System.Activities.Activity,我们在修改工作流名称的时候,也同时修改了类的名称
任务二修改程序启动的Main方法
WF4在WorkflowRuntime中运行工作流。
启动工作流最简单的方法就是通过WorkflowInvoker类的Invoke方法,默认下是WorkflowConsoleApplication模板所采用的启动方式。
此外,还可以通过更灵活多样的WorkflowApplication类来启动工作流,在以后的学习环节中也会学到。
学习时间
1分钟
步骤
1.为了解决编译错误,打开Program.cs并修改Main()方法中调用工作流的语句来使用SayHello类名。
2.找到WorkflowInvoker.Invoke位置,将Workflow1修改为SayHello:
staticvoidMain(string[]args)
{
WorkflowInvoker.Invoke(newSayHello());
}
验证
1.按CTRL+SHIFT+B编译项目
2.按CTRL+F5运行项目
VS2010学习笔记WF4(3)学习CodeActivity
学习时间:
5分钟
到目前为止,学习到WF4使用设计器编辑.xaml文件,并使用工作流运行时(WorkflowRuntime)启动工作流。
在创建工作流的时候,实际上是创建了继承于System.Activities.Activity或者它的子类的某个新类。
我们可以通过.xaml或者C#代码来创建新的activity类,这次我们就要学习如何通过继承CodeActivity来实现HelloWorkflow的功能。
Activity用于实现某个业务过程。
有些activity通过调用其它activity来实现这个目标。
例如之前的SayHello,它属于activity,但它并不直接输出字符串到控制台,而是通过WriteLine这个activity来完成的。
∙运行VS2010并打开之前创建的HelloWorkflow解决方案
∙右键点击HelloWorkflow项目,并选择Add/NewItem,从Workflow模板中选择CodeActivity并修改名称为SayHelloInCode
∙模板默认创建Text属性,这里用不着可以删除此属性
∙CodeActivity是抽象类,必须重载Execute方法
namespaceHelloWorkflow.Activities
{
classSayHelloInCode:
CodeActivity
{
protectedoverridevoidExecute(CodeActivityContextcontext)
{
Console.WriteLine("HelloWorkflow4incode");
}
}
}
∙打开Program.cs,修改Main()方法
staticvoidMain(string[]args)
{
WorkflowInvoker.Invoke(newSayHelloInCode());
}
∙按CTRL+SHIFT+B编译项目
∙按CTRL+F5运行项目,控制台输出应该如下
HelloWorkflow4incode
Pressanykeytocontinue...
为什么要在代码里实现业务逻辑?
从CodeActivity派生某个特别类的作用:
可以通过继承CodeActivity实现某个业务逻辑,并将之整合到其它大型业务逻辑中,提供更高的扩展性。
VS2010学习笔记WF4(4)使用xaml实现动态工作流
到目前为止,我们知道可以使用.xaml文件或者使用.cs文件来实现工作流,这些文件将被编译进程序集中。
使用.xaml文件比使用.cs文件有明显的好处:
∙工作流设计器只识别.xaml文件,使用.cs文件创建的工作流并没有可视化的设计器支持。
∙.xaml可以在运行时动态加载,无须编译进程序集
动态工作流提供了在运行时才生成业务逻辑,或在运行时才决定加载和运行哪个业务逻辑的可能性。
任务1–修改SayHello.xaml文件属性
修改SayHello.xaml文件的属性,使HellowWorkflow程序在运行时才加载和运行SayHello.xaml文件。
我们可以手工修改SayHello.xaml文件的内容,并运行程序看看修改后的输出消息是否有所变化。
∙首先修改SayHello.xaml文件的属性,使之被VS识别为部署内容,而不是内部代码:
o在SolutionExplorer选择SayHello.xaml
o在属性窗口,修改BuildAction为Content
o修改CopyToOutputDirectory为CopyAlways
任务2–修改Main()方法加载SayHello.xaml文件
SayHello.xaml在修改属性前,在编译的时候是作为类型编译到程序集。
要从.xaml文件中调用工作流,要使用ActivityXamlServices类来加载.xaml文件到内存并创建activity实例,便于WorkflowInvoker能够调用。
∙在program.cs文件加入System.Activities.XamlIntegration命名空间:
usingSystem.Activities.XamlIntegration;
∙修改Main()方法,使用ActivityXamlServices来动态调用.xaml文件。
同时加上Console.ReadKey以便控制台窗口保持显示状态:
staticvoidMain(string[]args)
{
WorkflowInvoker.Invoke(ActivityXamlServices.Load("SayHello.xaml"));
Console.ReadKey(false);
}
验证-运行并修改SayHello.xaml文件内容
通过修改发布到bin/Debug目录的SayHello.xaml文件内容,验证可在运行时动态加载工作流。
∙按CTRL+F5运行项目,程序在控制台输出HelloWorkflow4
∙通过Windows的资源管理器,定位到项目的Bin/Debug目录的SayHello.xaml
∙右键点击文件,并选择Edit
∙在记事本中,修改WriteLineactivity的Text属性为HelloWorkflow4XAML
∙通过Windows资源管理器,运行HelloWorkflow.exe,并观察修改后的输出结果是否HelloWorkflow4fromXAML
∙在VS中,重置SayHello.xaml文件属性:
oBuildAction:
XamlAppDef
oCopytoOutputDirectory:
Donotcopy
oCustomTool:
MSBuild:
Compile
VS2010学习笔记WF4(5)加入单元测试,实现测试驱动开发(TDD)
前几部分内容,学习到如何输出一个字符串到控制台,既不可以接受输入参数,也不能提供输出参数,与大部分的应用程序的需求不太一致。
同时,现在的形式也不太容易进行测试。
我们将修改SayHelloactivity,使之可以接收输入参数,也可以输出参数,而不是将消息输出到控制台,这样SayHello就可以被应用到其它的大型业务逻辑中。
SayHello需要达到的功能类似于以下的代码:
privatestaticstringSayHello(stringname)
{
return"Hello"+name+"fromWorkflow4";
}
任务1–添加新的单元测试项目到当前的解决方案
∙首先添加单元测试项目,以便验证工作流行为。
在SolutionExplorer右键点击HelloWorkflow解决方案,选择Add/NewProject并选择项目设置选项:
o已安装的模板:
VisualC#-->Test
o模板:
TestProject
o名称:
HelloWorkflow.Tests
∙添加引用到HelloWorkflow.Tests项目
o右键点击HelloWorkflow.Tests项目,选择AddReference
o在Projects页,选择HelloWorkflow项目以添加项目引用
o在.NET页,添加System.Activities库
∙右键点击UnitTest1.cs,重新名称为SayHelloFixture.cs,在提示是否对类名重新命名的时候选择Yes
任务2–创建测试方法
在实际实现功能之前,先创建一个测试方法,这是TDD的主要做法。
测试驱动式开发(TestDrivenDevelopment,TDD),是一种非常好的编程模式,根据业务逻辑,先设定好测试方法,然后再编码使其通过测试。
对比实现逻辑前后的测试结果,从failed到passed来达到业务逻辑的实施。
∙添加以下命名空间到SayHelloFixture.cs
usingSystem.Activities;
usingHelloWorkflow;
∙创建一个测试方法,使你的工作流能够以设想的方式进行。
打开SayHelloFixture.cs并将TestMethod1方法修改为ShouldReturnGreetingWithName
∙以下代码复制到此方法中
[TestMethod]
publicvoidShouldReturnGreetingWithName()
{
IDictionaryoutput;
output=WorkflowInvoker.Invoke(
newSayHello()
{
UserName="Test"
});
Assert.AreEqual("HelloTestfromWorkflow4",output["Greeting"]);
}
这里有2个知识点:
∙如何传递输入参数给工作流activity
o通过创建activiy实例时,利用.NET3.5/4初始化对象的简化代码,对公共属性(Property)直接赋值
o或者传递Dictionary实例,将匹配好的数据作为参数给Invoke调用
output=WorkflowInvoker.Invoke(
newSayHello(),
newDictionary()
{
{"UserName","Test"}
});
∙如何获取activity的输出参数
o输出参数是IDictionary类型,输出变量的名称作为字典的键值
任务3–编译程序看看测试结果
现在只是写好测试方法,并未在activity中实现,编译项目看看编译状态如何。
∙按CTRL+SHIFT+B编译程序,应该显示编译错误
oHelloWorldflow.SayHello并不存在UserName的定义
∙打开SayHello.xaml,在设计器的下方,有Variables,Arguments和Imports,分别对应节点内变量、输入输出参数和引用。
点击Arguments并添加参数
o参数1:
UserName,输入,字符串
o参数2:
Greeting,输出,字符串
∙在WF中,参数代表了流入或流出activity的数据
∙按CTRL+SHIFT+B编译,错误应该没有了
任务4–运行测试,可预想测试不会通过
要记住,TDD的做法是,编写好测试方法后,在没有真正实施功能之前,测试一定是不会被通过的,否则只能说明测试方法存在bug以至于测试成功(功能都没实现,怎么可能成功呢?
!
)
∙按CTRL+R,T运行当前范围内的单元测试,测试会被运行,但会失败,因为工作流节点现在并没有输出任何内容到Greeting输出参数
任务5–实现功能,使测试通过
∙在设计器打开SayHello.xaml
∙输出文本到控制台永远不能使测试通过,因此需要删除此节点,右键点击WriteLine节点并选择Delete
∙通过Assign节点赋值给Greeting
o从工具栏的Primitives组中选择Assign节点并拖动到设计界面
o设置Assign节点的To属性为Greeting
o输入Assign节点的Value属性
▪可以通过设计界面直接输入
▪或者通过属性窗口的右侧...按钮打开表达式编辑器(ExpressionEditor)窗口,输入更长的表达式
o属性Value的值设置为:
"Hello"&UserName&"fromWorkflow4"
▪注意,在WF表达式中,永远都只能使用VB表达式,所以如果要换行,必须使用下划线_
∙按CTRL+SHIFT+B编译,应该没有错误
验证–测试可以成功
∙通过Test菜单的Windows/TestView,打开TestView窗口
∙选择ShouldReturnGreetingWithName测试并点击RunSelection按钮
∙在TestResults窗口验证测试是否Passed
VS2010学习笔记WF4(6)使用WorkflowApplication启动工作流
到目前我们知道如何创建一个工作流节点(activity)和使用最简单的方法来启动工作流,就是使用WorkflowInvoker类。
WorkflowInvoker.Invoke方法比较简单,它属于同步调用,工作流启动的线程与调用程序的线程是一样的。
启动工作流另外一个方法是使用WorkflowApplication类,相对WorkflowInvoke类,它可以允许工作流在另外一个独立线程运行,提供了当工作流结束的时候可以调用的delegates。
比起不使用WF4,可以更加简单和快捷的创建多线程服务器或客户端程序。
这节会学习到,修改启动程序用WorkflowApplication来运行SayHello节点,并观察线程表现。
要求可以达到以下功能:
1.返回一个个性化的问候语
2.返回一个非零的Int32数值,代表工作流运行的managedthreadID
我们还是使用TDD的先写测试方法的做法,看看如何完成以上的要求。
任务1–编写测试,验证可以将工作流线程ID作为输出参数返回
∙在HelloWorkflow.Tests项目下,打开SayHelloFixture.cs,并添加以下命名空间:
usingSystem.Threading;
usingSystem.Diagnostics;
∙添加ShouldReturnWorkflowThread测试方法,代码如下:
///
///VerifiesthattheworkflowreturnsanOutArgument
///Name:
WorkflowThread
///Type:
Int32
///Value:
Non-Zero
///
[TestMethod]
publicvoidShouldReturnWorkflowThread()
{
varoutput=WorkflowInvoker.Invoke(
newSayHello()
{
UserName="Test"
});
Assert.IsTrue(output.ContainsKey("WorkflowThread"),
"SayHellomustcontainanOutArgumentnamedWorkflowThread");
//Don'tknowforsurewhatitisyet
varoutarg=output["WorkflowThread"];
Assert.IsInstanceOfType(outarg,typeof(Int32),
"WorkflowThreadmustbeoftypeInt32");
Assert.AreNotEqual(0,outarg,
"WorkflowThreadmustnotbezero");
Debug.WriteLine("Testthreadis"+
Thread.CurrentThread.ManagedThreadId);
Debug.WriteLine("Workflowthreadis"+outarg.ToString());
}
∙上述的代码测试了
ooutput字典里存在WorkflowThread输出参数
o该参数值是一个Int32类型
o该参数值不是0
∙按CTRL+R,A运行所有测试。
可以预料Shoul