Asp.Net教程,WinForm教程,Asp.Net MVC,vs2008教程,vs2010教程,Silverlight技术,源码下载,Asp.Net视频教程
全站热门标签
vs2010 Silverlight 存储过程 水晶报表 ADO.NET JavaScript LINQ AjaxPro DataGridView 面向对象 Extjs GridView XML DevExpress HTML教程 Oracle jQuery 分页 GDI+ Visual C++2010 MySQL Office2010 WPF MVC Dojo WCF4.0 VB.NET Sql2005 textbox cookie WCF WinForm Discuz!NT SQL经典语句 T-SQL checkbox ASPxGridView F# asp.net SQL VS2008新特性 DropDownList Access TreeView Ajax VS2008 页面执行时间 Flex 字符串 回调 VB2005 DataSet C#时间 ASP.NET性能优化 用户在线检测 动画
Framework C#技术 VB.NET VC.NET WCFWPF
当前位置: 主页 > WinForm教程 > WPF >

WCF学习序列(三):消息交换

时间:2009-10-13 23:31来源:未知 作者:admin 点击:

客户端和服务之间通过消息交换(Message Exchange)来完成方法调用和数据传递,WCF 定义了 3 种消息交换模式。

  1. Request/Reply

  这是缺省模式,又被称之为同步调用。在调用服务方法后需要等待服务的消息返回,即便该方法返回 void 类型。

[ServiceContract]
public interface IContract
{
  [OperationContract]
  void Test();
}
public class MyService : IContract
{
  public void Test()
  {
    Thread.Sleep(3000);
    Console.WriteLine("Test Execute:{0}", DateTime.Now);
  }
}
public class WcfTest
{
  public static void Test()
  {
    AppDomain.CreateDomain("Server").DoCallBack(delegate
    {
      ServiceHost host = new ServiceHost(typeof(MyService));
      host.AddServiceEndpoint(typeof(IContract), new BasicHttpBinding(), 
        "http://localhost:8080/myservice");
      host.Open();
    });
    ChannelFactory<IContract> factory = new ChannelFactory<IContract>(new BasicHttpBinding(), 
      "http://localhost:8080/myservice");
    IContract o = factory.CreateChannel();
    Console.WriteLine("Start:{0}", DateTime.Now);
    o.Test();
    Console.WriteLine("End:{0}", DateTime.Now);
  }
}

输出:

Start:2007-3-27 15:27:18
End:2007-3-27 15:27:18
Test Execute:2007-3-27 15:27:21

  3. duplex

  这种模式相对复杂一些,我们详细描述一下步骤:

  (1) 设计标准的服务契约。为了完成回调操作,我们必须指定 SessionMode 和回调类型。

[ServiceContract(SessionMode=SessionMode.Required, CallbackContract=typeof(ICallback))]
public interface IContract
{
  [OperationContract]
  void Test();
}

  (2) 设计回调接口类型。由于回调方法在客户端执行,因此无须添加 ServiceContractAttribute。对于回调操作,服务器无须获取其返回信息,因此添加 IsOneWay=true 特性参数。

public interface ICallback
{
  [OperationContract(IsOneWay=true)]
  void Call(DateTime d);
}

  (3) 实现服务契约。通过 OperationContext.Current.GetCallbackChannel 可以获取回调委托,进而完成调用。

public class MyService : IContract
{
  ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
  public void Test()
  {
    Console.WriteLine("Test AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
    callback.Call(DateTime.Now);
  }
}

  (4) 实现服务器。注意必须使用支持 Session 的 Binding 类型。

ServiceHost host = new ServiceHost(typeof(MyService));
host.AddServiceEndpoint(typeof(IContract), new WSDualHttpBinding(), "http://localhost:8080/myservice");
host.Open();(5) 创建客户端代理对象。利用 Svcutil 或者我们前面讲的方法创建客户端代理类型代码。(为显示方便,代码有所删减。)

//------------------------------------------------------------------------------
// <auto-generated>
//   此代码由工具生成。
//   运行库版本:2.0.50727.42
//
//   对此文件的更改可能会导致不正确的行为,并且如果
//   重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
[ServiceContractAttribute(ConfigurationName = "IContract", CallbackContract = typeof(IContractCallback), SessionMode = SessionMode.Required)]
public interface IContract
{
  [OperationContractAttribute(Action = "...", ReplyAction = "...")]
  void Test();
}
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface IContractCallback
{
  [OperationContractAttribute(IsOneWay = true, Action = "...")]
  void Call(System.DateTime d);
}
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public interface IContractChannel : IContract, IClientChannel
{
}
[DebuggerStepThroughAttribute()]
[GeneratedCodeAttribute("System.ServiceModel", "3.0.0.0")]
public partial class ContractClient : DuplexClientBase<IContract>, IContract
{
  public void Test()
  {
    base.Channel.Test();
  }
}

 

  (6) 实现客户端。

  创建新的客户端项目,将生成的代理文件加入。客户端除了要创建一个实现回调接口的类型外,还要为绑定对象指定一个监听端口,以便服务器与之联系。

class CallBack : IContractCallback
{
  public void Call(DateTime d)
  {
    Console.WriteLine("Call AppDomain:{0}", AppDomain.CurrentDomain.FriendlyName);
    Console.WriteLine("Server DateTime:{0}", d);
  }
}
[STAThread]
static void Main(string[] args)
{
  WSDualHttpBinding binding = new WSDualHttpBinding();
  binding.ClientBaseAddress = new Uri("http://localhost:8081/client");
  EndpointAddress address = new EndpointAddress("http://localhost:8080/myservice");
  ContractClient client = new ContractClient(new InstanceContext(new CallBack()), binding, address);
  client.Test();
}

  输出:

Server
--------------
Test AppDomain:Server
Client
--------------
Call AppDomain:Client.vshost.exe
Server DateTime:2007-3-27 17:01:39 

 

输出:

Start:2007-3-27 15:26:07
Test Execute:2007-3-27 15:26:10
End:2007-3-27 15:26:10

  2. one-way

  这种方式在调用方法后会立即返回,非常类似于异步行为。不过需要注意的是 one-way 不能用在非void,或者包含 out/ref 参数的方法上,会导致抛出 InvalidOperationException 异常。

[ServiceContract]
public interface IContract
{
  [OperationContract(IsOneWay=true)]
  void Test();
}
public class MyService : IContract
{
  public void Test()
  {
    Thread.Sleep(3000);
    Console.WriteLine("Test Execute:{0}", DateTime.Now);
  }
}
public class WcfTest
{
  public static void Test()
  {
    AppDomain.CreateDomain("Server").DoCallBack(delegate
    {
      ServiceHost host = new ServiceHost(typeof(MyService));
      host.AddServiceEndpoint(typeof(IContract), new BasicHttpBinding(), 
        "http://localhost:8080/myservice");    
      host.Open();
    });
    ChannelFactory<IContract> factory = new ChannelFactory<IContract>(
      new BasicHttpBinding(), "http://localhost:8080/myservice");
    IContract o = factory.CreateChannel();
    Console.WriteLine("Start:{0}", DateTime.Now);
    o.Test();
    Console.WriteLine("End:{0}", DateTime.Now);
  }
}

(责任编辑:admin)
Tags:WCF
责任编辑:admin
返回顶部
------分隔线----------------------------
推荐内容
骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价 骆驼户外男 真皮磨砂日常休闲鞋 低帮 2011秋冬新款 专柜正品特价