WCF入门(一)——简单的示例

这篇随笔写了一段时间了,当时没有发布,今天整理文档的时候发现了,顺便给配了些图。主要是绍了一下WCF编程模型,并给了一个简单的示例。

概述

WCF框架是下一代.NET平台通信应用程序的核心。它包含了Web服务、Remoting、同步和异步消息应用程序的开发,合并了所有最近有关的各种标准,建立了通过XML配置文件替代C#代码(如果你喜欢的话可以继续使用代码)对服务定义进行配置的模型。

WCF的设计思路是使开发者可以专注于开发所需的业务逻辑而不是增加工作(服务器和客户端之间的通信、数据传输等),WCF将为你处理这些问题,并且通过使用扩展的配置文件让一切变得更加容易实现。

 

WCF程序结构

一个完整的WCF解决方案包括如下四个部分:

  1. 契约(Contracts):    主要定义了实现那些服务,如何访问服务
  2. 服务(Services):        实现契约定义的方法
  3. 宿主程序(Hosting):    提供低层传输功能的支持
  4. 客户端(Client):        根据契约访问服务

下面我们就来逐一讲解如何实现一个简单的WCF程序。

 

实现契约和服务

契约通常是一个接口,定义了我们会提供哪些服务。以一个简单的计算器为例,假如我们要提供一个加减法的服务,则定义接口如下:

    public interface Icalculator
    {
        double Add(double x, double y);
        double Subtract(double x, double y);
    }

而服务则是如何实现这个契约,对于上述接口,实现方式如下:

    public class CalculatorService : Icalculator
    {
        public double Add(double x, double y)
        {
            return x + y;
        }

        public double Subtract(double x, double y)
        {
            return x - y;
        }
    }

对契约和服务有了基本了解后,我们就可以在WCF程序中实现它了,我们通常把契约和服务放在一个类库项目中实现,首先新建一个WCF服务库项目(也可以新建一个类库项目,然后添加System.ServiceModel.dll的引用):

使用WCF服务库项目模板创建项目后,发现系统会自动提供了一个简单的契约和服务的实现,在这里我们将其替换成前面定义的接口和实现。

  

首先把契约文件IService1.cs替换成我们的接口:

    [ServiceContract]
    public interface ICalculator
    {
        
[OperationContract]
        double Add(double x, double y);

        
[OperationContract]
        double Subtract(double x, double y);
    }

可以看到,和前面定义的基本接口有点区别的是:

  • 接口名称上加了 ServiceContract 属性
  • 接口方法上加了 OperationContract 属性

这个是告诉WCF宿主程序定义的契约名称和要实现的接口,否则WCF宿主程序也无法知道该如何加载服务。实现服务的代码和前面一样,这里就不列出来了。

实现完我们的服务和契约后,按Ctrl+F5后就可以直接测试了。虽然我们没有编写客户端,但系统自动提供了一个WcfTestClient供使用的:

关于WCF测试客户端的更多信息,可以参看MSDN文章:启用WCF测试客户端(WCF Test Client)的相关技巧

 

实现宿主程序

前面我们可以看到,编写WCF服务端程序时,虽然我们并没有实现宿主程序,但在客户端仍然能够访问服务。这是因为在测试Wcf库的时候,系统自动启动了一个宿主程序WcfSvcHost.exe,并加载了该服务,以便我们能测试访问。不过WcfSvcHost.exe只是一个轻量级的宿主程序,主要用于测试用,对于实际项目,我们可以把它部署到IIS中,都可以不用编写自己的宿主程序。

除了IIS外,我们也可以编写自己的宿主程序,通过一个控制台或窗口程序来实现宿主程序,这样也可以在没有IIS的机器上运行我们的服务,也可以更改低层传输协议,从而获取更高的传输效率等。

实现宿主程序也比较简单,首先创建一个控制台项目,然后添加System.ServiceModel.dll和前面定义的服务项目WcfService的引用,然后就可以实现宿主程序了:

        static void Main(string[] args)
        {
            ServiceHost host = new ServiceHost(typeof(CalculatorService));
            host.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "http://localhost:8733/Design_Time_Addresses/WcfService/Service1/");
            if (host.Description.Behaviors.Find<ServiceMetadataBehavior>() == null)
            {
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                behavior.HttpGetEnabled = true;
                behavior.HttpGetUrl = new Uri("http://localhost:8733/Design_Time_Addresses/WcfService/Service1/wsdl");
                host.Description.Behaviors.Add(behavior);
            }

            host.Open();

            Console.WriteLine("CalculaorService
已经启动,按任意键终止服务!
");

            Console.Read();
            host.Close();
        }

这里的大部分都是配置操作,这个配置对新手来说非常多,写在代码里也不好看,因此通常是写在App.Config中,我这里是直接把WcfService工程中<system.serviceModel>直接拷贝过来的。要修改这个配置,可以使用VisualStudio中的WCF服务配置编辑器。

  

把配置挪到App.Config中后,代码可以简化如下:

    static void Main(string[] args)
    {
        ServiceHost host = new ServiceHost(typeof(CalculatorService));
        host.Open();

        Console.WriteLine("CalculaorService
已经启动,按任意键终止服务!
");

        Console.Read();
        host.Close();
    }

从代码中可以看到,我们只需要创建一个ServiceHost对象,然后调用Open方法开启服务即可,并不需要什么额外的操作,非常简单。

 

实现客户端

要实现客户端,我们需要知道如下两个信息:

  1. 服务端提供了那些服务
  2. 该如何采取这些方式访问服务

这个信息可以通过宿主程序发布的wsdl获取,客户端无需知道服务区的实现细节,直接根据wsdl地址即可。例如,对于前面的例子中,我的服务地址是:http://localhost:8733/Design_Time_Addresses/WcfService/Service1/(在App.config中配置的),直接通过浏览器可以wsdl的发布地址,并能获取相关信息。

有了该信息后,借助VisualStudio的强大功能就可以非常快捷的实现客户端程序了。我们首先插件一个控制台程序,然后添加web服务引用:

添加该服务后,和WebService一样,系统自动生成了Client类。

借助这个Client类,就可以访问前面的服务了。

    static void Main(string[] args)
    {
        using (var proxy = new CalculatorClient())
        {
            Console.WriteLine("{0} + {1} = {2}", 3, 5, proxy.Add(3, 5));
            Console.WriteLine("{0} - {1} = {2}", 3, 5, proxy.Subtract(3, 5));
        }
    }

实际上,根据服务端发布的wsdl信息,也可以使用java等其它语言编写,是一种非常灵活的方式。

 

小结

从本文中的这个例子可以看出,WCF非常好的上屏蔽了低层细节(服务器和客户端之间的通信、数据传输等),开发者只需要关注业务逻辑即可,并且非常灵活,是一门非常优秀的RMI技术。

关于WCF园子里有许多文章,这些都是非常好的学习材料,我目前也只是处于管中窥豹的阶段,后续有空再写写相关文章。

  1. 我的WCF之旅(1):创建一个简单的WCF程序
  2. 我的WCF之旅(2):Endpoint Overview
  3. 我的WCF之旅(3):在WCF中实现双向通信(Bi-directional Communication)
  4. 我的WCF之旅(4):WCF中的序列化(Serialization)- Part I
  5. 我的WCF之旅(4):WCF中的序列化(Serialization)- Part II 
  6. 我的WCF之旅(5):Service Contract中的重载(Overloading)
  7. 我的WCF之旅(6):在Winform Application中调用Duplex Service出现TimeoutException的原因和解决方案
  8. 我的WCF之旅(7):面向服务架构(SOA)和面向对象编程(OOP)的结合——如何实现Service Contract的继承 
  9. 我的WCF之旅(8):WCF中的Session和Instancing Management 
  10. 我的WCF之旅(9):如何在WCF中使用tcpTrace来进行Soap Trace
  11. 我的WCF之旅(10): 如何在WCF进行Exception Handling 
  12. 我的WCF之旅(11):再谈WCF的双向通讯-基于Http的双向通讯 V.S. 基于TCP的双向通讯 
  13. 我的WCF之旅(12):使用MSMQ进行Reliable Messaging
  14. 我的WCF之旅(13):创建基于MSMQ的Responsive Service
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值