-我生君未生,君生我已老。 我离君天涯,君隔我海角。
-就像这首诗一样,WCF是个什么动动我也是从零开始学习,这篇文章主要是介绍如何实现一个WCF的示例,更多是告诉大家怎么做而非为什么这么做。深层次的问题,我们后面再深究。
话说WCF(Windows Communication Foundation)由微软发展的一组数据通信的应用程序开发接口。它为面向服务(Service Oriented)应用程序提供一个分布式编程框架,在.NET3.0引入,可以说是集分布式应用程序开发之大乘者。
为什么这么说呢,如果是.NET2.0和之前的版本,微软发展了Web Service,.NET Remoting,以及基础的 Winsock 等通信方法。而且每个通信方法的设计方法不同并且相互有重叠,例如 .NET Remoting 可以开发 SOAP, HTTP 通信。自然每一个通信方法都是要从新学习的,这就对像我这样被微软惯坏了的程序猿灰常的不友善了。
大幸的是,微软重新查看了这些通信方法,并设计了一个统一的程序开发模型,对于数据通信提供了最基本最有弹性的支持,这就是 Windows Communication Foundation。
PS:请大家不要鄙视我是因为想一劳永逸才学WCF=。=
------------------------------------约会开始-----------------------------------
今天我们的目的是牵手成功,为了够拉风,我们需要VS2008安装NET 3.0以上版本(这样才能创建WCF应用程序模板),不够拉风妹子不出门,你们懂的。
首先我们新建一个WCF服务应用程序,如果你的座驾够拉风,就会在如图1所示的地方找到WCF服务应用程序的模板。
图1
图2
完成之后呢,VS已经创建了一个WCF服务应用程序,并且提供给我们了一个简单的示例代码。结构如图2所示。
没有上述环境的同学,还有一种创建WCF服务应用程序的方法,需要分别创建4个项目来定义服务契约(Contracts),实现服务契约(Services),提供宿主(Hosting)和客户端(Client)。
这种方式在Artech的WCF之旅的第一篇有详述,我就不画蛇添足了。
IService1.cs:定义服务契约。VS生成的示例代码如下:

// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“IService1”。 [ServiceContract] public interface IService1 { [OperationContract] string GetData(int value); [OperationContract] CompositeType GetDataUsingDataContract(CompositeType composite); // TODO: 在此添加您的服务操作 } // 使用下面示例中说明的数据约定将复合类型添加到服务操作。 [DataContract] public class CompositeType { bool boolValue = true; string stringValue = "Hello "; [DataMember] public bool BoolValue { get { return boolValue; } set { boolValue = value; } } [DataMember] public string StringValue { get { return stringValue; } set { stringValue = value; } } }
我们可以看到IService1是一个接口,由特性[ServiceContract]来指示这个接口在应用程序中用来定义服务契约。
接口中的方法使用[OperationContract]特性来指示这个方法是服务契约的一个部份,可供远程调用。
CompositeType类是服务端和客户端之间要传送的自定义数据类型,使用[DataContract]特性来指示该类的示例对象可以被序列化在服务端和客户端之间传送。
但成员方法不会被传递。并且默认情况下除非使用[DataMember]特性来指示,不具有该特性的成员都被排除在外,也就是说,客户端程序不会获得被排除在外的成员的任何信息。
有人看到这肯定会喊,楼主是想拿VS生成的东西当示例?当然,我没准备学腾讯,既然我们是来牵手的,就写个牵手的例子把。
来修改一下服务契约,命名空间为JohnConnor.TakeYourHand
[ServiceContract] public interface ITakeYourHand { [OperationContract] Result FirstLook();//获取第一眼印象分 [OperationContract] Result ShowTime();//尝试表现下自己 [OperationContract] Result TakeHand(int Point);//尝试牵手 } [DataContract] public class Result { [DataMember] public int Score { get; set; } [DataMember] public bool Succeed { get; set; } [DataMember] public string Message { get; set; } }
ITakeYourHand接口定义了我们这个牵手服务程序的服务契约,Result则定义了一个数据协议,它可以作为客户端和服务端传递数据的载体。
Server1.svc:实现服务契约,当然这个文件还有一个特殊的用途:对WCF服务的调用就体现在对.svc文件的访问上,它本身还载有其他一些服务的属性信息(这个有木有人赐教一下?)。
现在我们把之前定义的接口在Server1.svc.cs里实现一下。命名空间不变。
public class TakeYourHand : ITakeYourHand { public Result FirstLook() { Random num = new Random(); Result result = new Result() { Score = num.Next(0, 10),//返回一个1~9的随机人品 Succeed = false }; result.Message = "第一印象" + result.Score + ",Good Luck!"; return result; } public Result TakeHand(int Point) { Random num = new Random(); Result result = new Result(); if (num.Next(Point, 11) == 10)//分数越大,成功几率越大 { result.Succeed = true; result.Score = 0; result.Message = "木有反抗,恭喜恭喜!"; } else { result.Succeed = false;//贸然牵手扣3分 result.Score = -3; result.Message = "心太急有木有,扣3分!"; } return result; } public Result ShowTime() { Random num = new Random();//随机的表现大于2则Good否则Bad, Result result = new Result(); if (num.Next(0, 10)>2) { result.Score = 1; result.Message = "帅气的表现征服了全场!加1分"; } else { result.Score = -1; result.Message = "扣鼻shi被妹子看见了!扣1分"; } result.Succeed = false; return result; } }
现在服务端已经大功告成拉。现在我们可以在解决方案资源管理器里选中Service1.svc,然后F5运行。
图3
如图3就会有一个Wcf测试客户端弹出来,服务添加成功后在浏览器输入显示的地址,
这里是http://localhost:5140/Service1.svc 就可以看到一些关于服务的信息了,这时候服务就是开启状态了。
这里得提一下WCF的核心ABC了,
- A:Address Where-WCF的Service都有一个唯一的地址。这个地址给出了Service的地址和传输协议(Transport Protocol)
- B:Binding How-通信(Communication)的方式
- C:Contract What-契约,描述了Service能提供的各种服务
上图中点击一下配置文件就可以看到:
<?xml version="1.0" encoding="utf-8"?> <configuration> <system.serviceModel> <bindings> <basicHttpBinding> <binding> <!--省略绑定的细节--> </binding> </basicHttpBinding> </bindings> <client> <endpoint address="http://localhost:5140/Service1.svc" binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ITakeYourHand" contract="ITakeYourHand" name="BasicHttpBinding_ITakeYourHand" /> </client> </system.serviceModel> </configuration>
endpoint标签里就描述了这三要素,地址address,绑定binding,契约contract。WCFbinding可以配置成BasicHttpBinding来兼容(或者说变身成)WebService。
下面我们继续来进行客户端的部份。演示如何来调用WCF服务。首先,我们来建一个控制台应用程序命名为JohnConnor.TakeYourHand.Client
首先必须保证服务在开启状态,然后右键添加服务引用,会弹出如图4的会话框:
图4 在地址栏中输入WCF客户测试端显示的地址并前往,就能看到服务的详细信息了。我们把命名空间改为
TakeYourHandService。确定,然后VS就会给我们生成一个服务引用和一个本地的app.config配置文件。
这时候 远程对象 就应该存在于JohnConnor.TakeYourHand.Client.TakeYourHandService命名空间之下了。首先我们把这个命名空间引用到Program头中。再来实现客户端:
class Program { static void Main(string[] args) { int Point = 0; Console.WriteLine("约会开始,按回车键测试你的第一印象分!"); Console.ReadLine(); using (TakeYourHandClient client = new TakeYourHandClient())//创建一个远程对象 { var result = client.FirstLook();//调用远程方法FirstLook Point += result.Score; Console.WriteLine(result.Message); while (!result.Succeed && Point >= 0 && Point < 10) { Console.WriteLine("当前分数:" + Point.ToString() + ".输入0尝试牵手,输入1来Show一下!回车确定"); var key = Console.ReadLine(); if (key == "0") { result = client.TakeHand(Point);//调用远程方法TakeHand Point += result.Score; Console.WriteLine(result.Message); } if (key == "1") { result = client.ShowTime();//调用远程方法TakeHand Point += result.Score; Console.WriteLine(result.Message); } else { Console.WriteLine("按规矩出牌,别乱来"); } } if (Point < 0) { Console.WriteLine("当前得分:" + Point.ToString()+",你被妹子甩了..."); } if (Point >= 10) { Console.WriteLine("妹子已主动牵起了你的手,恭喜恭喜!"); } Console.WriteLine("游戏结束"); Console.ReadKey(); } } }
TakeYourHandClient就是远程对象了。因为我们实现契约的类名为TakeYourHand,所以远程对象的命名一般是加Client作为后缀。在服务运行的时候,我们就可以调用远程对象提供的方法来做一些事情了。运行控制台程序:
看来我还是个高富帅的得分,8分,两下就让妹子主动牵手了吼吼!不知道各位会不会是屌丝或是穷矮矬的得分。。。。
---------------------------------------------------分割线-------------------------------------------------
我也是刚开始接触WCF,希望这个例子能帮助像我一样的初学者对WCF有一个初步的印象。文中有任何问题,欢迎指正,一起进步。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库