关于WCF引用方式之WCF服务寄宿控制台

1.创建解决方案WCFService

依次添加四个项目,如上图,Client和Hosting为控制台应用程序,Service和Service.Interface均为类库。

2.引用关系

Service.Interface:定义服务契约(Service Contract)接口,引用WCF核心库System.ServiceModel.dll;

Service:定义服务的项目,由于需要实现具体的服务,而服务契约在Service.Interface中,所以要引用Service.Interface项目;

Hosting:服务宿主的控制台程序,需要引用Service.Interface和Service项目,同时还要引用System.ServiceModel.dll类库:

Client:一个控制台应用程序的客户端,需要引用Service.ServiceModel类库。

Service.Interface:

服务契约抽象了服务的所有操作,一般契约为接口形式存在。

  [ServiceContract(Name = "CalculatorService", Namespace = "Listen.Fly")]
    public interface ICalculator
    {
        [OperationContract]
        double Add(double x, double y);

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

        [OperationContract]
        double Multiply(double x, double y);

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

通过使用System.ServiceModel.ContractAttribute特性来标识接口为服务契约,同时可以在特性中指定契约的Name和Namespace。通过ContractAttribute特性标识为契约后的接口的方法并不能自动成为服务操作,WCF采用的是显示选择策略,所以我们要在对应的服务操作上添加OperationContractAttribute特性。

Service:

在Service项目中添加类CalculatorService类,并实现自ICalculator接口,并将服务操作(加减乘除四个方法)代码补全。

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

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

        public double Multiply(double x, double y)
        {
            return x * y;
        }

        public double Divide(double x, double y)
        {
            return x / y;
        }
    }

 Hosting:

WCF服务需要一个运行着的宿主进程,服务寄宿就是给服务指定一个宿主的过程。WCF采用基于终结点(EndPoint)的通信手段。终结点有地址(Address),绑定(Binding)和契约(Contract)三部分组成,三要素也可以记作:EndPoint=ABC。

一个终结点包含了通信所必须的所有信息,具体如下:
Address:地址决定了服务的位置,解决了寻址的问题;
Binding:绑定实现了通信的所有细节,包括网络传输,消息编码,以及其他为实现某种功能(比如传输安全,可靠消息传输,事务等)对消息进行的相应处理。WCF中具有一系列的系统定义绑定,比如BasicHttpBinding,WSHttpBinding和NetTcpBinding等;
Contract:契约是对服务操作的抽象,也是对消息交换模式以及消息结构的定义。

服务寄宿的目的是开启一个进程,为WCF服务提供一个运行环境,并为服务添加一个或者多个终结点,然后暴漏给服务消费者。

Hosting的代码如下:

      using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
            {
                host.AddServiceEndpoint(
                    typeof(ICalculator),
                    new WSHttpBinding(),
                    "http://127.0.0.1:1111/CalculatorService");
                if (host.Description.Behaviors.Find() == null)
                {
                    ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
                    behavior.HttpGetEnabled = true;
                    behavior.HttpGetUrl = new Uri("http://127.0.0.1:1111/CalculatorService/metadata");
                    host.Description.Behaviors.Add(behavior);
                }
                host.Opened += delegate
                    {
                        Console.Write("CalculatorService已经启动,按任意键终止服务");
                    };
                host.Open();
                Console.Read();
            }

WCF的寄宿通过System.ServiceModel.ServiceHost对象来完成,我们代码中基于服务类型(typeof(CalculatorService))创建了ServiceHost对象。添加了基于WSHttpBinding绑定的终结点,服务契约类型为typeof(ICalculator),地址为"http://127.0.0.1:1111/CalculatorService"(此处的地址可以随意指定)。
  WCF中客户端和服务端是松耦合的,客户端只需要知道WCF服务的基本描述,而不需知道服务的具体实现,就可以完成调用。WCF服务的描述通过元数据(Metadata)的形式发布出来,WCF中的元数据通过一个特殊的服务行为ServiceMetadataBehavior来实现。
  在上述代码中我们为ServiceHost添加了ServiceMetadataBehavior这样一个服务行为,并采用基于HTTP-GET的元数据获取方式,并且通过ServiceMetadataBehavior的HttpGetUrl属性指定元数据的发布地址(当前地址为http://127.0.0.1:1111/CalculatorService/metadata)。在服务启动之后,访问该地址可以看到元数据,即为XML返回数据的页面。(也就是和我们通常点击svc文件中的链接看到的结果是一样的)

上面的代码实在是不太好记住,不过通常我们也不会这么做,可以将这些配置的过程放在config文件中去:

<</span>configuration>
  <</span>startup>
    <</span>supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
  </</span>startup>
  <</span>system.serviceModel>
    <</span>behaviors>
      <</span>serviceBehaviors>
        <</span>behavior name="metadataBehavior">
          <</span>serviceMetadata httpGetEnabled="true"   httpGetUrl="http://127.0.0.1:1111/CalculatorService/metadata"/>
        </</span>behavior>
      </</span>serviceBehaviors>
    </</span>behaviors>
    <</span>services>
      <</span>service name="Service.CalculatorService" behaviorConfiguration="metadataBehavior">
        <</span>endpoint address="http://127.0.0.1:1111/CalculatorService" binding="wsHttpBinding"
                            contract="Service.Interface.ICalculator"></</span>endpoint>
      </</span>service>
    </</span>services>
  </</span>system.serviceModel>
</</span>configuration>

打开Hosting项目中的app.config,添加上述代码即可。xml中的标签的意思和我们创建ServiceHost过程基本是一致的。

如果使用了配置文件的方式,我们的代码可以更简单,Hosting代码修改如下:

     using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
            {
                host.Opened += delegate
            {
              Console.Write("CalculatorService已经启动,按任意键终止服务");
            };
                host.Open();
                Console.Read();
            }

Client:

契约也定义了,服务也实现了,宿主也写好了,还剩下最后一步调用服务,运行Hosting.exe(debug目录下的哦,如果运行失败,那么请用管理员身份运行),然后看到如下界面:

然后在Client中添加对服务的引用:

在地址中输入我们配置的url,单击Go即可找到发布的WCF(必须要一直运行着Hosting.exe),可以在Namespace修改为自定义的命名空间,点击OK即可成功添加WCF。添加成功之后,被客户端调用的契约接口CalculatorService会被生成出来。客户端之所以会被命名为CalculatorService,是因为我们在ICalculator接口的特性中设置Name为CalculatorService。CalculatorService是与定义在Service.Interface项目中ICalculator接口等效的契约接口。但是我们在客户端使用则是一个CalculatorServiceClient(当然不同的WCF名称不一样,但是都是以Client结尾),CalculatorServiceClient的基类为System.ServiceModel.ClientBase。CalculatorServiceClient同样实现了契约接口CalculatorService,并通过从基类继承的Channel属性调用相对应的方法。

使用如下:

     using (CalculatorServiceClient proxy = new CalculatorServiceClient())
            {
                Console.WriteLine("x+y={2} when x={0} and y={1}", 1, 2, proxy.Add(1, 2));
                Console.WriteLine("x-y={2} when x={0} and y={1}", 10, 2, proxy.Subtract(10, 2));
                Console.WriteLine("x*y={2} when x={0} and y={1}", 10, 2, proxy.Multiply(10, 2));
                Console.WriteLine("x/y={2} when x={0} and y={1}", 10, 2, proxy.Divide(10, 2));
                Console.Read();
            }

很简单吧,只需定义一个xxClient对象,然后调用其对应的方法即可,当然我们现在使用的是同步的,每个方法都有对应的异步方法。比如Add对应的异步方法就是AddAsync,如果使用异步方法则要给xxClient添加对应的回调函数。
      客户端通过服务代理对象进行服务调用,上述代码中的通过添加服务引用自动创建生成的、继承自ClientBase的类型对象进行服务调用。实际上还有另外一种实现方法,通过System.ServiceModel.ChannelFactory直接创建服务代理对象。WCF采用基于契约的服务调用方法,从上述代码中可以看到,VS在添加服务引用的过程中,会在客户端创建一个与服务等效的服务契约接口。由于服务端和客户端都在同一个解决方案,因此可以让服务端和客户端引用相同的契约。

客户端使用第二种方法也就是ChannelFactory形式创建代理对象,删除掉之前添加的WCF的引用,然后添加对Service.Interface项目的引用(注:如果客户端是Silverlight应用程序可能会提示无法添加,因为Silverlight应用程序只能添加Silverlight应用程序或者Silverlight类库),然后修改代码如下:

      using (ChannelFactory channelFactory = new ChannelFactory(
                new WSHttpBinding(),
                "http://127.0.0.1:1111/CalculatorService"))
            {
                ICalculator proxy = channelFactory.CreateChannel();
                Console.WriteLine("x+y={2} when x={0} and y={1}", 1, 2, proxy.Add(1, 2));
                Console.WriteLine("x-y={2} when x={0} and y={1}", 10, 2, proxy.Subtract(10, 2));
                Console.WriteLine("x*y={2} when x={0} and y={1}", 10, 2, proxy.Multiply(10, 2));
                Console.WriteLine("x/y={2} when x={0} and y={1}", 10, 2, proxy.Divide(10, 2));
            }

终结点是WCF进行通信的唯一方式,ChannelFactory本质上是通过指定的终结点创建用于进行服务调用的服务代理。上述嗲吗中,在创建ChannelFactory的时候在构造函数中指定了终结点的ABC三要素,其中地址和绑定则通过参数指定,契约提现在ChannelFactory的泛型参数上。不过一般我们也不会这么做,聪明的你猜到了,还是通过配置文件来进行,没错,配置如下:

<</span>configuration>
  <</span>system.serviceModel>
    <</span>client>
      <</span>endpoint
        name="CalculatorService"
        address="http://127.0.0.1:1111/CalculatorService"
        binding="wsHttpBinding"
        contract="Service.Interface.ICalculator"  />
    </</span>client>
  </</span>system.serviceModel>
</</span>configuration>

在配置文件中添加了endpoint,同样还是指定了address地址、binding绑定、以及契约constract和代码创建的过程一致哦。

代码修改如下:

  using (ChannelFactory channelFactory = new ChannelFactory("CalculatorService"))
            {
                ICalculator proxy = channelFactory.CreateChannel();
                Console.WriteLine("x+y={2} when x={0} and y={1}", 1, 2, proxy.Add(1, 2));
                Console.WriteLine("x-y={2} when x={0} and y={1}", 10, 2, proxy.Subtract(10, 2));
                Console.WriteLine("x*y={2} when x={0} and y={1}", 10, 2, proxy.Multiply(10, 2));
                Console.WriteLine("x/y={2} when x={0} and y={1}", 10, 2, proxy.Divide(10, 2));
            }

可以看到,唯一的区别就是在对ChannelFactory实例化的时候,使用配置文件中endpoint的name属性替代了之前的Binding和地址。

 注:上述代码中如果是非添加服务引用的方式进行创建Client,那么在运行Client的时候,请确保Hosting.exe已经正常启动。

原文地址:https://www.cnblogs.com/lvjy-net/p/8297638.html

时间: 2024-10-11 22:23:10

关于WCF引用方式之WCF服务寄宿控制台的相关文章

WCF引用方式之IIS方式寄宿服务

通过IIS方式寄宿服务 之前的例子是将控制台作为WCF的寄宿方式或者是直接添加契约项目的引用,然后通过配置或者是ChannelFactory的形式进行创建服务对象,其实在大多的开发中以IIS的形式创建WCF也是比较常见的.每一个Webservice都是具有一个asmx文本文件,客户端通过访问.asmx文件即可实现Webservice的调用.当然WCF和Webservice类似,每一个WCF服务都有一个对应的.svc文本文件.基于IIS服务寄宿要求的WCF服务都具有相应的.svc文件,.svc文件

微软 WCF的几种寄宿方式,寄宿IIS、寄宿winform、寄宿控制台、寄宿Windows服务

WCF寄宿方式是一种非常灵活的操作,可以在IIS服务.Windows服务.Winform程序.控制台程序中进行寄宿,从而实现WCF服务的运行,为调用者方便.高效提供服务调用.本文分别对这几种方式进行详细介绍并开发例子进行说明,以求大家对WCF寄宿的方式进行全面的认识和了解. 1. WCF服务的IIS服务寄宿 我在我前面几篇WCF开发框架的介绍文章中,介绍过了WCF常用的一种寄宿方式,IIS服务寄宿.这种寄宿方式是最为方便的方式,而且由于服务只需要IIS运行就能自动运行起来,因此广为使用. 创建这

通过代码的方式完成WCF服务的寄宿工作

使用纯代码的方式进行服务寄宿 服务寄宿的目的是为了开启一个进程,为WCF服务提供一个运行的环境.通过为服务添加一个或者多个终结点,使之暴露给潜在的服务消费,服务消费者通过匹配的终结点对该服务进行调用,除去上面的两种寄宿方式,还可以以纯代码的方式实现服务的寄宿工作. 新建立一个控制台应用程序,添加System.ServiceModel库文件的引用. 添加WCF服务接口:ISchool使用ServiceContract进行接口约束,OperationContract进行行为约束 1 using Sy

WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]

原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码和配置:通过ChannelFactory<TChannel>创建服务代理对象.在这篇文章中,我们采用一种独特的方式进行服务的调用.从本质上讲,我们只要能够创建于服务端相匹配的终结点,就能够实现正常的服务调用.在WCF客户端元数据架构体系中,利用MetadataExchangeClient可以获取服

创建WCF服务寄宿到IIS

一.WCF简介: Windows Communication Foundation(WCF)是由微软开发的一系列支持数据通信的应用程序框架,可以翻译为Windows 通讯开发平台. 整合了原有的windows通讯的 .net Remoting,WebService,Socket的机制,并融合有HTTP和FTP的相关技术. 由 .NET Framework 3.0 开始引入. WCF的最终目标是通过进程或不同的系统.通过本地网络或是通过Internet收发客户和服务之间的消息. WCF合并了Web

WCF服务寄宿IIS与Windows服务

WCF是Windows平台下程序间通讯的应用程序框架.整合和 .net Remoting,WebService,Socket的机制,是用来开发windows平台上分布式开发的最佳选择.wcf程序的运行需要一个宿主ServiceHost,我们可以选用控制台应用程序,也可以选择IIS寄宿,还可以选择windows 服务寄宿.相较与控制台程序,IIS,和Windows服务比较稳定.而且大家不会时不时的去重启下IIS下的网站,或者windows服务. 在IIS下寄宿Wcf 我们新建一个类库项目 在项目下

WCF配置与服务寄宿

1.项目框架如下: 2.WCF服务项目 其中WCFService中存放服务契约及其实现,需添加命名空间:System.ServiceModel 3.服务寄宿 WCFHost是一个控制台程序,用于寄宿WCF服务,需添加命名空间:System.ServiceModel和引用WCFService项目 其中需要编写的代码如下: 若直接在配置文件里配置终结点信息,则对于的代码如下: 配置文件信息如下: 4.客户端 需添加命名空间:System.ServiceModel和引用WCFService项目 客户端

Post方式调用wcf服务

我们平常在PC端调用WCF服务,只要知道WCF服务的地址,客户端直接添加引用服务就可以使用了,殊不知还有其他方式,其实,我们也可以 通过HTTP POST的方式调用WCF服务,这样就不用添加引用了,在手机移动端开发后台服务,都是通过Post的形式调用WCF服务,当然,这种方式在PC也可以使用. 我们来看下面的一个简单示例.下面的示例演示了服务器端和客户端的简单通讯 服务器端返回一个JSON字符串,代码如下 契约定义 [csharp] view plaincopy [OperationContra

WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿

原文:[原创]WCF技术剖析之三:如何进行基于非HTTP的IIS服务寄宿 在上面一篇文章中,我们对不同版本的IIS,以及ASP.NET得的实现机制进行了详细而深入的分析.在介绍IIS7.0的时候,我们谈到,HTTP.SYS+W3SVC实现了基于HTTP的请求监听,在此基础上引入了以下三组网络监听器(Listener)和监听适配器(Adapter),实现了基于TCP.Named Pipes和MSMQ的网络监听,图1揭示了IIS7的总体结构. TCPListener|TCP Listener Ada