前言:

WCF初探-5:WCF消息交换模式之双工通讯(Duplex)博文中,我讲解了双工通信服务的一个应用场景,即订阅和发布模式,这一篇,我将通过一个消息发送的例子讲解一下WCF客户端如何为双工服务创建回调对象。

双工服务指定一个回调协定,客户端应用程序必须实现该协定以便提供一个该服务能够根据协定要求调用的回调对象。虽然回调对象不是完整的服务(例如,您无法使用回调对象启动一个通道),但是为了实现和配置,这些回调对象可以被视为一种服务。

双工服务的客户端必须:

  • 实现一个回调协定类。
  • 创建回调协定实现类的一个实例,并使用该实例创建传递给 WCF 客户端构造函数的 System.ServiceModel.InstanceContext 对象。
  • 调用操作并处理操作回调。

双工 WCF 客户端对象除了会公开支持回调所必需的功能(包括回调服务的配置)以外,其他的功能和它们的非双工对应项相同。

示例说明:

  • Service服务契约中定义了一个发送方法Send,采用IsOneWay=true,供客户端调用,向服务端发送消息。Service中还提供了用于双工通信的回调接口IMessageExchangeCallback,该接口中定义了服务端接收消息后向客户端发送消息的方法Receive,此方法就是客户端发送消息到服务端后,服务端调用回调方法,将消息发送到客户端。
  • Client需要实现双工协定回调接口的类CallBackHandler,并实现Receive方法。
  • 针对双工协定生成的 WCF 客户端需要在构造时提供一个 InstanceContext 类。此 InstanceContext 类用作实现回调接口并处理从服务发送回的消息的对象所在的位置。InstanceContext 类是用 CallbackHandler 类的实例构造的。此对象处理通过回调接口从服务发送到客户端的消息。

  

 WCF客户端为双工服务创建回调对象示例

 

  • 解决方案如下:

  

  • 工程结构说明:
  1. Service:类库程序,定义服务契约接口和回调接口,实现服务契约。在IMessageExchange中定义了Send方法,并且还定义了双工服务回调接口 IMessageExchangeCallback。

    IMessageExchange.cs的代码如下:

using System.ServiceModel;
using System.Collections.Generic;
using System.Runtime.Serialization; namespace Service
{
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMessageExchangeCallback))]
public interface IMessageExchange
{
[OperationContract(IsOneWay=true)]
void Send(string message);
} public interface IMessageExchangeCallback
{
[OperationContract(IsOneWay = true)]
void Receive(string message);
}
}

    MessageExchange.cs的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel; namespace Service
{
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
public class MessageExchange : IMessageExchange
{
public void Send(string message)
{
Console.WriteLine("服务端监听客户端发出的消息:" + message);
Callback.Receive(message); } IMessageExchangeCallback Callback
{
get
{
return OperationContext.Current.GetCallbackChannel<IMessageExchangeCallback>();
}
}
}
}

注意:回调契约接口IMessageExchangeCallback中的Receive方法是在客户端实现的,所以如果需要在服务端调用回调方法就必须通过当前操作的实例上下文来获取,即上面代码中的Callback对象。

  2.  Host:控制台应用程序。提供服务寄宿程序,添加对Srevice程序集的引用。完成配置文件和代码就可以承载服务。

    Program.cs的代码如下:

  

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Service;
using System.ServiceModel; namespace Host
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(MessageExchange)))
{
host.Opened += delegate { Console.WriteLine("服务已经启动,按任意键终止!"); };
host.Open();
Console.Read();
}
}
}
}

    App.config的代码如下:

  

<?xml version="1.0"?>
<configuration>
<system.serviceModel> <services>
<service name="Service.MessageExchange" behaviorConfiguration="mexBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:1234/MessageExchange/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsDualHttpBinding" contract="Service.IMessageExchange" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services> <behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors> </system.serviceModel>
</configuration>

  3.  Client:控制台应用程序。客户端程序,启动服务承载程序Host后,添加对服务地址http://localhost:1234/MessageExchange/的引用,将命名空间修改为

    MessageExchangeServiceRef,之后在Program.cs完成对双工服务回调接口IMessageExchangeCallback的实现和对服务方法的调用。Program.cs的代码如下:

using System;
using Client.MessageExchangeServiceRef;
using System.ServiceModel; namespace Client1
{ public class CallBackHandler : IMessageExchangeCallback
{
public void Receive(string message)
{
Console.WriteLine("客户端监听服务端接收的消息:" + message);
}
} class Program
{
static void Main(string[] args)
{
InstanceContext instanceContext = new InstanceContext(new CallBackHandler());
MessageExchangeClient proxy = new MessageExchangeClient(instanceContext);
proxy.Send("Wcf Duplex"); Console.Read();
}
}
}

  运行结果如下:

  

总结:

  • 本文模拟了客户端向服务端发送消息,服务端接收到消息后,将监听到的消息显示在客户端。希望通过本示例对双工通信有进步一的认识,关于实例和会话,我将在后面的博文中做解析。

WCF初探-13:WCF客户端为双工服务创建回调对象的更多相关文章

  1. BEGINNING SHAREPOINT&#174; 2013 DEVELOPMENT 第13章节--使用业务连接服务创建业务线解决方式 SP Apps中的BCS

    BEGINNING SHAREPOINT® 2013 DEVELOPMENT 第13章节--使用业务连接服务创建业务线解决方式  SP Apps中的BCS         之前的联系中,你安装了一个业 ...

  2. WCF系列教程之客户端异步调用服务

    本文参考自http://www.cnblogs.com/wangweimutou/p/4409227.html,纯属读书笔记,加深记忆 一.简介 在前面的随笔中,详细的介绍了WCF客户端服务的调用方法 ...

  3. WCF初探-14:WCF服务协定

    前言: 在前面的文章中,我们定义的服务协定上都会有一个ServiceContract的特性来修饰,这是因为服务契约的实现要靠ServiceContractAttribute 属性定义,然后使用一个或多 ...

  4. WCF初探文章列表

    WCF初探-1:认识WCF WCF初探-6:WCF服务配置 WCF初探-2:手动实现WCF程序 WCF初探-7:WCF服务配置工具使用 WCF初探-3:WCF消息交换模式之单向模式 WCF初探-8:W ...

  5. WCF初探-15:WCF操作协定

    前言: 在前面的文章中,我们定义服务协定时,在它的操作方法上都会加上OperationContract特性,此特性属于OperationContractAttribute 类,将OperationCo ...

  6. 【WCF系列】(四)WCF客户端怎么消费服务

    WCF客户端怎么消费服务 获取服务绑定协议.绑定和地址:实现方式 SvcUtil方式:SvcUtil.exe是一个命令行工具,位于:C:\Program Files (x86)\Microsoft S ...

  7. 【WCF全析(一)】--服务协定及消息模式

    上周微软开发布会说.NET支持完全跨平台和并开放Core源码的新闻,让我们顿时感到.NET要迎来它的春天.虽然早在几年前.NET就能开发Android和IOS,但是这次的跨平台把Linux都放到了微软 ...

  8. WCF初探-10:WCF客户端调用服务

    创建WCF 服务客户端应用程序需要执行下列步骤: 获取服务终结点的服务协定.绑定以及地址信息 使用该信息创建 WCF 客户端 调用操作 关闭该 WCF 客户端对象 WCF客户端调用服务存在以下特点: ...

  9. WCF初探-11:WCF客户端异步调用服务

    前言: 在上一篇WCF初探-10:WCF客户端调用服务 中,我详细介绍了WCF客户端调用服务的方法,但是,这些操作都是同步进行的.有时我们需要长时间处理应用程序并得到返回结果,但又不想影响程序后面代码 ...

随机推荐

  1. Leetcode: Partition Equal Subset Sum

    Given a non-empty array containing only positive integers, find if the array can be partitioned into ...

  2. Mysql常用命令行大全

    第一招.mysql服务的启动和停止 net stop mysql net start mysql 第二招.登陆mysql 语法如下: mysql -u用户名 -p用户密码 键入命令mysql -uro ...

  3. Android应用权限管理总结

      访问登记属性 android.permission.ACCESS_CHECKIN_PROPERTIES ,读取或写入登记check-in数据库属性表的权限 获取错略位置 android.permi ...

  4. Why does pthread_cond_signal not work?【转】

    转自:http://stackoverflow.com/questions/16819169/why-does-pthread-cond-signal-not-work# 0 down vote fa ...

  5. Dynamics AX 2012 R2 将系统用户账号连接到工作人员记录

    要使用AX中的一些特性,需要将User Account和他们的Employee Record连接在一起.最好将所有Employee的User Account,都和他们的Employee Record连 ...

  6. Dynamics AX 2012 R2 从代码中调用SSRS Report

    平时,我们制作SSRS Report的方法主要有两种:使用Query或RDP.如果需要为报表传递参数,就要在代码中为报表参数赋值,然后在代码中调用报表.下面我总结下这两种报表在代码中传参和调用的方式: ...

  7. 用jxl导出数据到excel

    需要jxl.jar 测试结果没问题,代码: package com; import java.io.File; import java.io.IOException; import java.util ...

  8. OS X 下iso刻录U盘

    1. 查看盘 $diskutil list /dev/disk0 #: TYPE NAME SIZE IDENTIFIER : GUID_partition_scheme *320.1 GB disk ...

  9. 【Redis】Redis的基本安装及使用

    在Linux上安装Redis Redis的安装很简单.基本上是下载.解压.运行安装脚本.我用的Redis版本是3.2.1. [nicchagil@localhost app]$ wget -q htt ...

  10. [问题2014A08] 解答

    [问题2014A08] 解答 由假设知 \(f(A)=\mathrm{tr}(AA')\), 因此 \[f(PAP^{-1})=\mathrm{tr}(PAP^{-1}(P')^{-1}A'P')=\ ...