最近在学习WCF,读的是蒋金楠老师牛B闪闪的《WCF技术剖析》,准备做个笔记加深下印象。老啦记不住东西喽,~_~
WCF微软平台的新一代分布式通信技术,意思是有了这个以前的web service,.net remoting,消息队列都可以通吃了,听起来很厉害的样子,哈哈。
构造WCF应用的步骤是:创建服务(定义服务协定,实现协定,配置服务),发布服务(或者说应用程序中承载服务),客户端调用服务。似乎跟web service一样。
1、WCF创建服务,类似web service,通过定义具有指定特性的接口来实现,特性定义在System.ServiceMode这个程序集里。
using System.serviceModel: namespace WcfDemo.Contracts { [ServiceContract(Name="CalculatorService",Namespace="http://www.itfad.net")] public interface ICalculator { [OperationContract] double Add(double x, double y); [OperationContract] double Subtract(double x, double y); } }以上代码定义的接口就叫做服务契约,真正的服务就是实现该接口了。
2、WCF服务发布,可以发布在IIS、控制台应用程序、winform程序都行,很闪吧,这个通常叫服务寄宿。说白了就是我定义了一堆服务类,
但这些类肯定不能独立存在啊,我得把它们放在一个可以启动的项目里。
既然是要对外发布,那类似我们的web程序,就得有服务地址,通信协议,数据传输格式,编码什么的。这些东西在WCF里叫
地址(Address)、绑定(Binding)、契约(Contract),三个东西组成了终结点(Endpoint)。WCF的通信正是基于终结点的,其实跟其它通信
技术也是类似的,只是换了个名字而已,当然功能上也是有增强的。再记录下对这三个东西的理解:
地址(Address):也就是服务的位置了,简单点就是一个URI,还可以加个消息头(似乎又想起了http的头了)。对应的类是EndpointAddress。
绑定(Binding) :WCF可以支持http|https,tcp/ip等协议,定义了一系列对应的绑定BasicHttpBinding,NetTcpBinding等。它们实现了通信中的细节,包括传输,编码,安全事务等处理。
契约(Contract) :对提供的服务功能的抽象,类似接口。
编码实现服务寄宿,同时配置了服务的三要素
class Program { static void Main(string[] args) { /*手动设置终结点和服务行为*/ //Calculator实现了服务接口 using (ServiceHost host = new ServiceHost(typeof(Calculator)))
{ //指定终结点,使用WSHttpBinding绑定 host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://127.0.0.1:8888/CalculatorService"); if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null) { ServiceMetadataBehavior behavior = new ServiceMetadataBehavior(); //元数据发布 behavior.HttpGetEnabled = true; behavior.HttpGetUrl = new Uri("http://127.0.0.1:8888/CalculatorService/metadata");//使用http的get方式获取元数据 host.Description.Behaviors.Add(behavior); host.Opened += delegate { Console.WriteLine("serivce started up,press any key to stop service"); }; host.Open(); Console.Read(); } } }
3、WCF的调用,在visual studio里也非常类似web service,点击“添加服务引用”然后给出服务元数据发布的源地址(我们这里是http://127.0.0.1:8888/CalculatorService/metadata),记住一定要运行WCF寄宿的程序才能连接上哦,接着会帮你生成对应的服务契约接口和服务代理对象。
通过调用服务代理对象来对服务调用,这些代理对象都继承了System.ServiceModel.ClientBase<T>这个类,名称是服务名+Client。
using (CalculatorServiceClient calService = new CalculatorServiceClient()) { Console.WriteLine("2+3="+calService.Add(2, 3)); }
还有另外一种创建服务代理的方法,通过ChannelFactory<T>,这里要先添加对服务契约接口的引用,代码如下:
//这里使用的是配置文件,所以未在代码中指定三要素
//calculatorService是配置里终结点的名称
using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
{
ICalculator service = channelFactory.CreateChannel();
using (service as IDisposable)
{
Console.WriteLine("5+99="+service.Add(5, 99));
}
}
需要注意的一点是,使用VS生成的配置的终结点约束是contract="CalculatorService.CalculatorService“,如果使用第二种方式创建服务代理时应将约束改为接口全名即contract="Wcf.Contracts.ICalculator”,否则会报InvalidOperationException异常提示找不到名称“XXX”和协定“XXX”的终结点元素。因为
ChannelFactory<T>是自己生成代理后调用而不是使用我们前面VS生成的CalculatorService代理。
一个简单WCF应用这样的基本OK了。
再回顾下通过配置实现以上代码
打开VS2010,"工具"菜单—"WCF服务配置编辑器",就是它了。
新建配置—新建服务,主要是设置前面提到的三要素,指定“服务类型”时选择的是你WCF服务所在的程序集(契约),接下来是选择通信方式(绑定),设定地址。
再新建服务行为,也就是元数据获取方式。“高级” - “服务行为” 新建后添加一个ServiceMetaData设定获取方式的地址即可,属性跟着上面的代码。
点击刚新建的服务设定behaviorConfiguration属性为新建的服务行为名称
保存配置文件到你的应用目录下,再看看生成的配置文件
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior0">
<serviceMetadata httpGetEnabled="true" httpGetUrl="http://127.0.0.1:8888/CalculatorService/metadata" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<!-- 设定服务名,终结点(地址,绑定,契约) -->
<service behaviorConfiguration="NewBehavior0" name="Wcf.Services.Calculator">
<endpoint address="http://127.0.0.1:8888/CalculatorService" binding="wsHttpBinding"
bindingConfiguration="" contract="Wcf.Contracts.ICalculator" />
</service>
</services>
</system.serviceModel>
</configuration>
服务配置完成,寄宿的代码就简单很多了
//使用配置文件 using (ServiceHost host = new ServiceHost(typeof(Calculator))) { host.Opened += delegate { Console.WriteLine("serivce started up,press any key to stop service"); }; host.Open(); Console.Read(); }