WCF 概念

源文地址

WCF 概念:

    WCF 是 “Windows Communication Foundation ”的缩写,Windows Communication Foundation (WCF) 是一个运行库和一组 API,用于创建在服务与客户端之间发送消息的系统。 它使用相同的基础结构和 API 来创建应用程序,这些应用程序可与同一计算机系统上或驻留在另一家公司内并通过 Internet 访问的系统上的其他应用程序进行通信。

    WCF 通过一种面向服务的新型编程模型简化了关联应用程序的开发。通过提供分层的体系结构,WCF 支持多种风格的分布式应用程序开发。 WCF 通道体系结构在底层提供了异步的非类型化消息传递基元。

WCF体系结构图

       

Contract(契约) :

    在WCF中所有需要向外部服务的方法或对象都需要标明契约属性。

    基本契约有4种:

服务契约(Service Contract) :

指示接口或类在 Windows Communication Foundation (WCF) 应用程序中定义服务协定。

数据契约(Data Contract) :

指定该类型要定义或实现一个数据协定,并可由序列化程序(如 System.Runtime.Serialization.DataContractSerializer)进行序列化。若要使其类型可序列化,类型作者必须为其类型定义数据协定。

异常契约(Fault Contract):

指定服务操作遇到处理错误时返回的一个或多个 SOAP 错误

消息契约(Message Contract):

定义与 SOAP 消息相对应的强类型类。

 

 

简单WCFService创建:

 

    WCF服务端:

    这里创建一个最简单,以Web形式发布的WCFService,现在这里创建一个“WCF 服务应用程序”名为 “WebWcfServiceA

   

    项目需要 System.ServiceModel 与 System.Runtime.Serialization 的引用。基本上所有有关于WCF的项目,都会需要到引用这两个组件。

   

    此项目中有一个接口 IWebWcfServiceA 用于表示WCF公开的方法。

    [ServiceContract]

    public interface IWebWcfServiceA

    {

        [OperationContract]

        string serviceFunction(int value);

    }

         这里接口中的契约属性ServiceContract 用于标明这个接口是公开可调用的。

         方法中的契约属性 OperationContract 用于标明这个方法是公开可调用的。

   

         除了接口外,还需要一个WCF服务文件 ,在这里命名为“WebWcfServiceA.svc”。

    public class WebWcfServiceA : IWebWcfServiceA

    {

        public string serviceFunction(int value)

        {

            return string.Format("You entered: {0}", value);

        }

    }

         这个类是WCF的主体,它继承于WCF公开的接口并完成接口的功能。

   

   

         这里需要注意的是,所有对接口ServiceContract 和服务文件 WebWcfServiceA.svc进行过名称更改的,都需要在配置文件中进行相应的更改。

       在配置文件中的 <system.serviceModel>节里面说明了WCF相关的配置,在这里需要注意的是元素service  endpoint  service  name 属性指名了WCF 服务类的位置;endpoint contract 属性指名了契约接口的位置。

客户端:

         现在为这个简单的WCFService创建一个简单的客户端,控制台程序“WebWcfAClient”。

   

         最简单创建客户端的办法就是像创建Web Service那样添加一个服务引用,这个服务引用直接指向刚才创建的WebWcfServiceA项目。

         创建成功后,项目会添加一份app.config,此文件记录了关于WCF服务的信息,其中这里需要注意一下的是client 中的 endpointaddress ,这里记录了指向WCF 服务的路径。

         创建这样一个服务引用后,便可以直接调用其中暴露出来的方法。

        static void Main()

        {

            WebWcfServiceA.WebWcfServiceAClient ServiceA = new WebWcfAClient.WebWcfServiceA.WebWcfServiceAClient();

            Console.WriteLine(ServiceA.serviceFunction(0));

            Console.ReadKey();

            ServiceA.Close();

        }

    这种客户端方式的调用,基本和webService的调用相似。

第二种WcfService创建:

    因为公开暴露的方法是在接口上,所以除了使用服务引用的办法来创建客户端引用外,还可以通过使用引用该接口的办法来调用WCF的服务。

   

    契约接口:

        

         首先,创建一个接口项目(IWebWcfServiceB)用于服务端和客户端双方的调用:

    [ServiceContract]

    public interface IService

    {

        [OperationContract]

        CompositeType serviceFunction(int value);

    }

    [DataContract]

    public class CompositeType

    {

        [DataMember]

        public string strValue

        {

            get;

            set;

        }

    }

这里的CompositeType类的属性DataContract(数据契约)用于标明此类是用在于WCF服务中提供数据的,并且此类是可以序列化的。

         属性strValue上的DataMember属性标明属性strValue可以序列化。

    服务端:

   

    服务段只有一个文件WebWcfServiceB.svc 

    public class WebWcfServiceB : IService

    {

        public CompositeType serviceFunction(int value)

        {

            CompositeType ct = new CompositeType();

            ct.strValue = string.Format("You entered: {0}", value);

            return ct;

        }

    }

    它基本和WebWcfServiceB.svc一致,只是继承的接口被分离到另外一个项目中。

   

    客户端:

   

    客户端需要引用接口IWebWcfServiceB,还需要为接口创建一个代理类,用于调用WCF服务。

    这个接口类可以手工创建,但是你运行打开上述的WebWcfServiceB.svc 文件时候会发现VS提供了一个工具svcutil.exe 来创建这个代理类。

         这里是一个手工写的代理类:

    public partial class ServiceClient : System.ServiceModel.ClientBase<IService>, IService

    {

        public ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) :

            base(binding, remoteAddress)

        {

        }

        public CompositeType serviceFunction(int value)

        {

            return base.Channel.serviceFunction(value);

        }

    }

    [DataContractAttribute]

    public partial class CompositeType : object, System.Runtime.Serialization.IExtensibleDataObject

    {

        public System.Runtime.Serialization.ExtensionDataObject ExtensionData

        {

            get;

            set;

        }

        [DataMemberAttribute]

        public string strValue

        {

            get;

            set;

        }

    }

    需要注意的是这里的命名空间要和公开接口的命名空间一致。

    如果使用工具写出的代码会有更多的实现方法,并且工具将会输出一个名为output.config 的文件,此文件和使用服务引用时添加的配置文件一样。

         代理类的使用如下:

            System.ServiceModel.WSHttpBinding binding = new System.ServiceModel.WSHttpBinding();

            System.ServiceModel.EndpointAddress address =

                new System.ServiceModel.EndpointAddress(new Uri("http://localhost/WebWcfServiceB.svc"));

            ServiceClient ServiceB = new ServiceClient(binding, address);

            CompositeType ct = ServiceB.serviceFunction(0);

            Console.WriteLine(ct.strValue);

            Console.ReadKey();

            ServiceB.Close();

         如果是使用配置文件的,可以直接ServiceClient ServiceB = new ServiceClient() 来读取调用配置文件中的路径。

WCF服务库:

          除了使用上面两种以WCF服务文件为主体,依附IIS的创建方式以外,还可以使用WCF服务库来创建WCF服务。

         直接创建一个WCF服务库,可以看见IDE为你创建了三份文件,一个公开契约的接口,一个控制台应用程序的WCF服务主体,和一份配置文件。

         这个结构和之前创建WCF 服务应用程序基本相同,只不过是主体由svc服务文件变为了控制台的应用程序。

         服务端:

    项目名称:HostWcfServiceA

    [ServiceContract]

    public interface IService

    {

        [OperationContract]

        string serviceFunction(int value);

    }

    public class HostWcfServiceA : IService

    {

        public string serviceFunction(int value)

        {

            return string.Format("You entered: {0}", value);

        }

    }

此服务运行后将会根据配置文件中baseAddress属性的地址来监听,该地址只是用于通信,不能使用浏览器打开。

    客户端:

    创建一个新的控制台程序HostWcfAClient 来作为客户端,客户端对此WCF服务的调用也可以使用服务引用,具体调用和WCF服务文件的方式一样。

服务端除了使用配置文件来配置监听路径外,还可以使用代码来配置监听路径,方法是使用另外一个应用程序来作为服务主机,让客户端调用。

    服务端B

    此服务端B的服务库与项目HostWcfServiceA 的服务库一样,添加多一个控制台应用程序作为服务器:

            Uri baseAddress = new Uri("http://127.0.0.1:55555");

            using (ServiceHost host = new ServiceHost(typeof(HostWcfServiceB.HostWcfServiceB), new Uri[] { baseAddress }))

            {

                BasicHttpBinding binding = new BasicHttpBinding();

                host.AddServiceEndpoint(typeof(HostWcfServiceB.IService), binding, baseAddress);

                host.Open();

                Console.WriteLine("服务已启动");

                Console.Read();

            }

最后声明: 此文只是本人学习WCF中的一点笔记,如有错谬,请指正。

本文源代码下载

Leave a Reply