第二讲:WCF介绍(2)
代码
https://yunpan.cn/cPns5DkGnRGNs 密码:3913
在上一讲中我们说到 在代码 当中 完成了 服务的寄宿。
这里我们说下 在实际的开发 当中 我们一般不会去使用代码的方式去完成服务的寄宿,一般都是 通过配置文件的方式 去完成服务器的寄宿。
所以我们这里介绍下 关于 配置文件 服务的寄宿
应用程序 启动起来之后 它会自动的去读取 应用程序配置文件
忘记提醒 我所使用的开发工具为 VS2013 ,Sqlserver2012
好,我们继续
我们打开 Hosting 项目 的 App.config 文件
里面键入
[ 2-01 ]
解释一下 这里的配置:
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <startup> 4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 5 </startup> 6 7 8 9 <!--WCF服务寄宿的配置 Start --> 10 11 12 13 14 <!--首先需要添加一个节点--> 15 <system.serviceModel> 16 17 <!--这里就是行为的集合--> 18 <behaviors> 19 <!--这里是绑定的行为--> 20 <serviceBehaviors> 21 <!--那么绑定的行为具体是什么行为 这里 name 给它起个名字--> 22 <behavior name="metadataBehavior"> 23 <!--配置这个行为可以 HTTP GET形式的访问(httpGetEnabled="true") 然后指定元数据地址(httpGetUrl="http://127.0.0.1:6666/calculatorservice/metadata")--> 24 <serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:6666/calculatorservice/metadata"/> 25 </behavior> 26 </serviceBehaviors> 27 </behaviors> 28 29 <!--这里就是当前整个服务的配置--> 30 <services> 31 <!--然后这里 《 引用具体的行文,将刚才配置的行为名称写到这里(behaviorConfiguration="metadataBehavior") 》 并且 《 契约的 实现服务( name="Services.CalculatorService" ) 注意:必须写 项目的 完整名称 必须加上 空间的名称 》 --> 32 <service behaviorConfiguration="metadataBehavior" name="Services.CalculatorService"> 33 <!--终结点 EndPoint 的配置 A,B,C 注意: 这里的 C 契约 必须写 项目的 完整名称 必须加上 空间的名称 --> 34 <endpoint address="http://127.0.0.1:6666/calculatorservice" binding="wsHttpBinding" contract="Contracts.ICalculator"></endpoint> 35 </service> 36 </services> 37 38 </system.serviceModel> 39 40 41 42 43 <!--WCF服务寄宿的配置 End --> 44 45 46 </configuration>
好,这里我们完成 了 Web.config 的配置
注意这里 为EndPoint 配置 URL 本地 访问地址的时候 一定 要指定 端口号
接下来我们来看看 寄宿 的 代码
按照之前的代码肯定会出错的,所以这里需要重新修改一下:
[ 2-02 ]
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.ServiceModel; 5 using System.ServiceModel.Description; 6 using System.Text; 7 using System.Threading.Tasks; 8 using Contracts; 9 using Services; 10 11 namespace Hosting 12 { 13 class Program 14 { 15 static void Main(string[] args) 16 { 17 //首先提供一个主机进程,实际上就是完成寄宿的主机( CalculatorService 完成了对契约的实现,所以我们这里就寄宿就寄宿它了 ) 18 using (var host = new ServiceHost(typeof(CalculatorService))) 19 { 20 //指定一个事件,当服务启动之后 需要做什么,这里指定一个委托,在 Open 成功后,就执行这里的事件 21 host.Opened += (sender, eventArgs) => Console.WriteLine("服务已经启动,按任何按钮停止"); 22 //开启服务 23 host.Open(); 24 Console.Read(); 25 } 26 } 27 } 28 }
好这里我们就完成了 WebConfig 方式的 寄宿
可以运行起来试一下,好,完好,这里就不再贴图片了。
接下来我们来说说 客户端 调用服务
客户端 调用服务
首先我们需要 先启动 Hosting
找到Hosting 的 控制台程序 启动 , 然后 Client 项目 引用 添加服务引用 输入上面我们 发布的元数据地址:http://127.0.0.1:6666/calculatorservice/metadata
看图
[ 2-03 ]
[ 2-04 ]
好了,这里我们的服务就引用成功了。
就多了个 “ Service References ” 的文件夹
并且 看我们的客户端的 WebConfig 中 也多出了 一些配置,这些配置是微软自动帮我们生成的, 而这些配置的相关节点 跟我们 服务端 的 配置 几乎相同。
[ 2-05 ]
好的 关于 配置文件我们就说到这里,后面我们会继续讲到。
前面 我们的 添加服务引用 已经添加引用了,配置文件也 自动生成好了 。
接下来,就是 客户端的 代码问题了:
首先我们看下 我们 添加的服务
[ 2-06 ]
双击 ” CalculatorClient “ 进入
[ 2-07 ]
由此我们可见 CalculatorClient 继承与 System.ServiceModel.ClientBase, System.ServiceModel.ClientBase是 提供基实现,用于创建可调用服务的 Windows Communication Foundation (WCF) 客户端对象。
所以,这里如果我们要调用 服务的方法,就必须先创建 CalculatorClient ,说白了 CalculatorClient 就是我们客户端的 代理
[ 2-08 ]
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 using Client.CalculatorService; 7 8 namespace Client 9 { 10 class Program 11 { 12 static void Main(string[] args) 13 { 14 //创建客户端代理 15 var proxy = new CalculatorClient(); 16 //调用服务的方法(这里 看下 之前 的契约,这个 Add 的方法 就是从契约中暴露出来的) 17 var returnvar = proxy.Add(1, 2); 18 //输出 19 Console.WriteLine(returnvar); 20 Console.Read(); 21 } 22 } 23 }
所有的 工作 都完成了,我们测试一下:
[ 2-09 ]
[ 2-10 ]
好的 ,也都 运行正常 !
上面我们说的通过服务引用的方式来调用服务方法,还有一种 是 创建信道工厂的方式去 完成 服务的调用,说实在的,我更倾向于 第二种信道工厂的方式去创建服务代理,因为信道工厂更加灵活。
信道工厂 ChannelFactory
我们来修改下客户端的代码:
[ 2-11 ]
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.ServiceModel; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Contracts; 8 9 namespace Client 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //信道工厂 16 //建立服务通信的代理,这里也是参数,A,B,C 17 using (ChannelFactory<ICalculator> changFactory = new ChannelFactory<ICalculator>(new WSHttpBinding(), "http://127.0.0.1:6666/calculatorservice")) 18 { 19 //建立通道 20 ICalculator proxy = changFactory.CreateChannel(); 21 //通道使用完成之后自动销毁 22 using (proxy as IDisposable) 23 { 24 //服务调用 25 var returnvar = proxy.Add(1, 2); 26 Console.WriteLine(returnvar); 27 Console.Read(); 28 } 29 } 30 } 31 } 32 }
既然服务器的 都推荐 使用 配置文件方式 配置 服务的寄宿
那么我们 客户端 就不能 使用配置文件的方式 去配置 EndPoint 访问点,答案当是 可以的。
[ 2-12 ]
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <startup> 4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 5 </startup> 6 <system.serviceModel> 7 <client> 8 <endpoint address="http://127.0.0.1:6666/calculatorservice" binding="wsHttpBinding" contract="Contracts.ICalculator" name="calculatorservice"></endpoint> 9 </client> 10 </system.serviceModel> 11 </configuration>
当然 客户端 的代码 也发生的 响应的变化:
[ 2-13 ]
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.ServiceModel; 5 using System.Text; 6 using System.Threading.Tasks; 7 using Contracts; 8 9 namespace Client 10 { 11 class Program 12 { 13 static void Main(string[] args) 14 { 15 //信道工厂 16 using (ChannelFactory<ICalculator> changFactory = new ChannelFactory<ICalculator>("calculatorservice")) 17 { 18 //建立通道 19 ICalculator proxy = changFactory.CreateChannel(); 20 //通道使用完成之后自动销毁 21 using (proxy as IDisposable) 22 { 23 var returnvar = proxy.Add(1, 2); 24 Console.WriteLine(returnvar); 25 Console.Read(); 26 } 27 28 } 29 30 } 31 } 32 }
到这里我们 就可以感受到了 协议与客户端之间的关系?
客户端与服务之间应该共享契约,而不是代码,也就是它们之间的耦合性不是基于代码的耦合,而是基于契约的。在契约中不包含具体的服务逻辑,这样为我们构建松耦合的分布式系统提供了良好的技术。
契约与元数据最终生成客户端代理和配置.
好了,我们就先介绍到这里吧。
再这之前,我们都是稍微了解下 WCF 的 创建,后面我们再将 一些细节 例如 契约(几种契约,每种契约的特点 等),绑定协议(几种绑定协议,几种绑定协议的不同点 等) ........
结束