Microsoft NLayerApp案例理论与实践 - 分布式服务
Microsoft NLayerApp采用基于WCF的分布式服务组件为外界(各种类型的GUI)提供了访问接口,客户端程序只需要添加Service引用即可使用NLayerApp应用程序所提供的功能。在NLayerApp中,分布式服务部分的设计与结构还是比较简单的,主要包括DistributedServices.Core、DistributedServices.MainModule以及DistributedServices.Deployment三个项目。
DistributedServices.Core
该项目为所有位于分布式服务层的组件提供公共的类型定义与功能实现,比如在这个项目中定义了与异常处理相关的Fault Contract类型与特性(Attribute)定义。
DistributedServices.MainModule
该项目根据NLayerApp应用程序本身的需求,设计了所需的DTO、服务契约(Service Contract)、操作契约(Operation Contract),并根据模块划分,用C#的partial class特性分别实现了银行管理、客户管理和销售管理三个部分的操作。IMainModuleService接口中定义了NLayerApp的分布式服务所能提供的所有操作接口,而MainModuleService部分类则实现了该接口。根据模块划分的不同,MainModuleService类的实现部分被分配到三个不同的文件中:MainModuleService.BankingManagement.cs、MainModuleService.CustomersManagement.cs和MainModuleService.SalesManagement.cs。
打开IMainModuleService.cs文件,我们可以看到,对于所有的方法,无论是方法的参数还是返回值,都是以原始数据类型(Primitive Data Types)或者DTO的形式实现数据传输的。NLayerApp将Domain Entities同时作为DTO来处理,有关DTO以及Domain Entities as DTOs的详细内容,请参考上篇《Microsoft NLayerApp案例理论与实践 - 应用层》一文,这里就不再多说了。
在IMainModuleService接口的实现类MainModuleService类中,各方法都通过IoC容器(前面也详细讲过IoC容器,NLayerApp事实上使用的是Microsoft Unity)获得应用层组件的实例,从而执行相应的操作。通过上文我们可以得知,NLayerApp在应用层中也是使用IoC容器来获得仓储、领域服务(Domain Service)的具体实现的,由此可见,NLayerApp在层与层之间就是使用的IoC容器实现分层解耦。以下是MainModuleService类中GetBankAccounts方法的实现代码,从中我们可以了解到分布式服务中IoC容器的使用方式。
public List<BankAccount> GetBankAccounts(BankAccountInformation bankAccountInformation) { //Resolve root dependency and perform operation IBankingManagementService bankingManagement = IoCFactory .Instance .CurrentContainer .Resolve<IBankingManagementService>(); List<BankAccount> bankAccounts = null; //perform work! bankAccounts = bankingManagement.FindBankAccounts ( bankAccountInformation.BankAccountNumber, bankAccountInformation.CustomerName); return bankAccounts; }
DistributedServices.Deployment
该项目其实就是一个WCF Web Application,它是分布式服务的宿主项目,它可以以Web应用程序的方式部署到ASP.NET Web Server(比如IIS)上。该项目下的MainModule.svc文件定义了所使用的WCF Service(也就是DistributedServices.MainModule项目中的MainModuleService类);而web.config文件则对如下信息进行了配置:
- 用于Entity Framework的连接字符串
- 所使用的IoC容器的名称
- 用于诊断和跟踪程序的配置信息
- Web Application的配置信息
- WCF Service的配置信息
在部署NLayerApp的时候,需要将DistributedService.Deployment项目部署到ASP.NET Web Server(比如IIS)上,并启动Web服务器,之后,客户端程序即可通过WCF的客户端配置以及代理类来访问NLayerApp的应用程序了。
分布式服务程序的调试
我们可以用soapUI工具来进行分布式服务的调试。soapUI是一款先进的开源的针对Web Service的调试与测试工具,你可以点击此处查看该工具的官网首页,并从中获得下载链接。现在,让我们开始使用soapUI来进行分布式服务程序的调试(由于本人的系统是英文版,为了避免翻译的不准确性以致误导读者,因此请读者朋友们自行参照自己的中文版系统进行演练)。
- 成功编译NLayerApp
- 在DistributedServices.Deployment项目下,找到MainModule.svc文件,右键单击并选择View in Browser,这将启动ASP.NET Development Server,并在IE浏览器中展示如下页面:
- 启动soapUI,在Navigator Panel中,右键单击Projects节点,选择New soapUI Project,此时弹出New soapUI Project对话框,在Initial WSDL/WADL文本框中输入http://localhost:88/MainModule.svc?wsdl,此时Project Name文本框会自动以“MainModule”填充,暂时别管其它的选项,直接单击OK按钮
- 在Navigator Panel中展开MainModule节点,我们可以看到,它包含两个Endpoint:WS2007ForIntranetClients和BasicBindingForSliverlightClients,这与DistributedServices.Deployment项目的web.config中的配置是相符的
- 展开BasicBindingForSliverlightClients节点,我们可以看到由IMainModuleService接口所发布的所有方法,展开GetCustomerByCode操作,并双击Request 1,在打开的Request 1对话框中,左边部分列出了调用该操作的SOAP Envelope
- 在<mic:customerCode>节点上输入A0001,我们获得如下Request XML:
<soapenv:Envelope xmlns:soapenv=http://schemas.xmlsoap.org/soap/envelope/
xmlns:mic="Microsoft.Samples.NLayerApp.DistributedServices.MainModuleService"> <soapenv:Header/> <soapenv:Body> <mic:GetCustomerByCode> <!--Optional:--> <mic:customerCode>A0001</mic:customerCode> </mic:GetCustomerByCode> </soapenv:Body> </soapenv:Envelope> - 单击Request 1对话框左上角的绿色箭头,将直接调用GetCustomerByCode方法,并获得返回结果
- 要调试分布式服务,首先设置好断点,然后在Visual Studio中选择Debug –> Attach to Process菜单,在弹出的Attach to Process对话框中,选择ASP.NET Development Server – Port 88,然后单击Attach按钮,这将使Visual Studio进入调试模式
- 再次单击Request 1对话框中的绿色箭头以调用分布式服务,此时程序的执行将会停在断点处,供开发人员调试
总结
本文主要对NLayerApp的分布式服务所涉及的各个项目做了简单介绍,同时还给出了一个实践案例,对分布式服务的测试与调试进行了详细演示。分布式服务部分是客户端程序与NLayerApp应用程序进行交互的接口部分,不包含任何业务逻辑与任务协调操作,它只是一种通讯手段的技术实现。
NLayerApp的介绍也差不多快结束了,本系列文章将不再继续对其GUI部分做详细叙述了,因为GUI部分的开发与特定技术的结合非常紧密,比如WPF、Sliverlight以及ASP.NET MVC,有关这些内容,读者可以参考相关资料一起阅读学习,本系列文章就不再继续对WPF、Sliverlight以及ASP.NET MVC这些技术本身做进一步介绍了。