• 使用Class Library项目模板创建服务


    一. 前言 

          前一章,我们介绍了如何使用WCF的项目模板来构建WCF服务,使用这种方式,我们在调试的时候可以不用构建宿主服务程序,可以延期至发布软件。接下来我们将利用[类库]项目模板来构建服务,这种方式可以使我们更好的理解WCF服务,同时更随意的构建。我们总结出实现过程如下:

          1. 构建服务主体(定义契约,实现服务类型,配置终结点);

          2. 创建服务宿主程序(承载服务)

          3. 创建客户端程序(SvcUtil.exe生成客户端代理类,供客户端调用服务);

          在本例程中,我们依然使用计算器服务[这个例子比较经典],提供了四种操作:加、减、乘、除。

    二. 构建服务主体 

          1.  在构建WCF服务时,我们一般从定义契约开始。契约定义了终结点所能提供的操作,契约定义好以后,实现契约即服务类型(service type),从真正意义上定义了契约的操作。首先,通过Visual Studio 2010创建一个空白解决方案Calculator:

          2.  创建一个类库(Class Library)项目,这里命名为Calculator(命名空间:Po.App.Calculator),用于构建我们的计算器服务。在这类库中我们我们需要引用System.ServiceModel程序集。在这个类库中,我们定义计算器服务契约如下:

    计算器服务契约

          3.  实现服务类型,这里我们定义了CalculatorService,实现如下:

    计算器服务类型

          4.  指定地址和绑定。WCF终结点包含了地址、绑定和契约。目前为止,计算器服务访问的终结点的契约已经定义好并且实现了,我们还需要提供地址和绑定以完成终结点的定义。WCF提供了一个编辑工具,即Service Configuration Editor,帮助我们完成配置工作,我们在《WCF编程实战系列(t):Service Configuration Editor工具介绍》详细介绍了这款工具的使用。为了深入理解WCF配置语言(《WCF编程实战系列(t):配置语言揭秘》),本章中我们将进行手动配置。在Calculator工程下添加App.config文件,将其内容作如下配置:

    地址绑定配置清单1

          5.  激活元数据发布,需要在配置文件中添加一个激活元素据发布的行为设定,修改App.config文件,将其内容作如下配置:

    地址绑定配置清单2

          6.  至此,初步完成了我们的计算器服务。

    三. 承载服务 

          1.  接下来我们需要提供一个应用程序域(application domain)来承载服务。应用程序域是微软的CLR为程序集(assembly)提供的容器。因此,为了让应用程序域承载WCF服务,需要有Windows进程为该服务初始化CLR,任何.NET可执行程序都可以用来做这件事情比如IIS,WPF,Winform,控制台等等。本例中我们将使用控制台承载服务。首先添加一个控制台项目(Console Application),命名为CalculatorHost,添加对System.ServiceModel和System.Configuration程序集的引用,服务宿主程序示范代码如下:

    服务宿主程序

         2.  现在来启动下服务宿主,看看是否能够正常启动,结果如下:

          3.  产生异常的原因是无法找到终结点或终结点未定义,无法找到配置文件。解决这个办法我们需要在当前工程(CalculatorHost)创建一个与服务同样的配置文件,在VS上可以将Calculator工程下的App.config直接拖拽至当前工程下,便会产生一个配置文件副本,代码与地址绑定配置清单2一致。在此启动服务宿主,运行结果如下:

          4.  从目前情况来看,服务似乎可以正常使用了。接下来我们验证下,启动服务宿主程序,然后我们通过WCF测试客户端(VS命令行->wcftestclient)进行下测试:

           5.  从异常信息中,我们得知:服务添加失败,元数据不可访问。确保服务运行并且暴漏服务元数据。为了搞清楚这个问题,我们需要搞清几个问题:WCF服务元数据是什么?为什么要暴露服务元数据?WCF服务元数据交换终结点是怎么回事?

        (1)WCF服务元数据是什么?

           WCF服务元数据是WCF服务的核心部分服务地址(Address)、绑定(通信协议Binding)、契约(服务、操作、数据Contract)的原始描述信息。服务所公开的元数据包括 XSD(文档中出现的元素、文档中出现的属性、子元素、子元素的数量、子元素的顺序、元素是否为空、元素和属性的数据类型、元素或属性的默认和固定值)和 WSDL 文档(用于描述服务的方法、参数、参数个数、顺序、返回值、返回值的类型等方法的相关信息)。.Disco文档(描述服务的协议、地址、命名空间等信息)。

           这些关键的WCF服务元数据全部都是基于XML语言描述,支持核心的行业标准协议。XSD好处显而易见,  基于XML,没有专门的语法 ,XML Schema支持一系列的数据类型(int、float、Boolean、date等) ,可扩充的数据模型,支持综合命名空间 ,支持属性组等。而这些正式WCF分布式服务追求的跨语言、跨平台的关键部分所在。

              (2)为什么要暴露服务元数据?

           知道了WCF服务元数据的概念后,我们就能理解为什么要暴露服务的元数据。WCF服务的元数据描述服务的核心信息,客户端需要了解这些特征以便与该服务进行通信。要想实现异构平台或者系统之间的通信,以前的技术是使用Web Service.因为其具有自描述、可扩展、与平台无关等优势。客户端只需要根据Web Service地址,便可获取服务的相关信息,反序列话本地的代码,通过服务代理进行服务的调用。

          WCF服务主要特性之一就是跨平台的服务交互。而暴露服务元数据的重要原因就是解决了异构客户端服务交互的关键问题。 元数据基于XML,自描述。客户端可以根据服务的元数据反序列换生成本地代码,无论是c#,vb还是java语。

                (3)WCF服务元数据交终结点是怎么回事?

          WCF服务有两种方案可以发布自己的元数据。一种是基于HTTP-GET协议提供元数据;另一种则为MEX终结点元数据交换方式,和WCF服务一样使用一个专门的终结点,称为MEX元数据交换终结点。元数据交换终结点与其它终结点相似,包含自己的地址(Address)、绑定(通信协议Binding)、契约(服务、操作、数据Contract),但是使用的服务契约为WCF提供的接口IMetadataExchange。两种发布元数据的方式使用了两种不同的标准网络传输协议,前者为HTTP/GET请求,后者为WS-MetadataExchange(MEX:WCF支持的基本绑定HTTP、HTTPS、TCP、IPC等绑定协议)。

          对于WebService来说,它是通过WSDL的方式发布元数据,这样对于WebService来说,是自动发布服务的元数据信息,于是我们可以通过WSDL工具生成WebService的代理类。在WCF中,服务是可以选择不发布元数据信息的,即使是对于它所支持跨平台HTTP协议。

          WCF自动为服务宿主自动提供了IMetadataExchange接口的实现。对于元数据交换终结点,WCF提供了专门的绑定元素用以对不同的协议(如:HTTP、TCP、IPC)的支持。如HTTP则对应mexHttpBinding;对于Tcp则对应mexTcpBinding;对于IPC则对应mexNamedPipeBinding。以下就是对于HTTP、TCP、IPC这几种协议下元数据交换终结点的配置:

    元数据交换终结点

    这样,不管服务所支持的HTTP、TCP、IPC等方式,我们都可以通过SVCUtil工具生成代理类,进而访问服务。在WCF中,对于HTTP协议而言,我们可以通过直接配置服务的行为,通过httpGetEnabled="true"的方式来发布服务的元数据信息,而它不支持其他协议;对于其他协议我们希望发布元数据信息,通过配置的方式显然是一种很好的方式。

           6.  根据以上信息及服务宿主程序的异常我们得知:我们需要在服务宿主中发布元数据,修改CalculatorHost项目下的App.config文件,作如下配置:

    宿主服务终结点配置清单

           7.  重新生成当前工程,启动服务。通过WCF测试客户端再次进行测试,结果如下:

           8.  至此,我们的服务已经可以正常使用了。 

    四. 创建客户端,调用服务 

           1.  为了测试我们的服务,我们新建一个控制台项目,命名为ClientTest,用于测试对服务的调用。客户代理类的创建有两种方式:a.添加服务引用自动生成。b.使用svcutil.exe工具生成。本例程中我们使用工具手动生成代理类。首先,确保我们的服务正常启动。然后打开SDK命令窗口,输入E:  在输入cd E:\Data\cnblogs\Calculator\Calculator,使计算器服务所在目录成为当前目录。最后输入svcutil http://localhost:8000/Po/App/ /out:Proxy/Client.cs /config:Proxy/app.config,操作过程及结果如下:

           2.  将Proxy文件夹拷贝到ClientTest工程下,并包含到工程里。我们客户端调用逻辑如下:

    客户端测试代码

                 测试结果如下:

    五. 总结 

          1.  本章主要介绍了如何使用类库项目构建WCF服务,这样可以使我们对WCF服务的理解和运用的更加游刃有余。同时,本章针对元数据终结点进行了重点讲解。另外,通过SvcUtil.exe能够帮助我们更灵活和自由的创建客户端代理。如果您对以上某个知识点难以理解或有疑问,敬请留言!

          2.  本例程源代码

    零之轨迹博客:天空之城

    作者:何健东
    出处:http://traxex.cnblogs.com/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    通过串口抓取图片
    Qt也有垃圾回收(通过QScopedPointer实现),下决心在项目里使用QScopedPointer,省了太多事情了,而且更安全!!
    IOS端 margin-top 和 margin-bottom 使用负数时的区别
    使用ROME解析rss,如何获取icon图标
    SVG图片如何调整大小和颜色
    Js点击触发Css3的动画Animations、过渡Transitions效果
    如何判断是否为同一个App,Ionic3如何修改包名
    如何使用JPQL写纯SQL语句
    为何在新线程中使用注解获取不到Spring管理的Bean
    Ionic的NavController 和ModalController 的区别
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/2631973.html
Copyright © 2020-2023  润新知