子曾经曰过

  博客园  :: 首页  ::  ::  ::  :: 管理

IOperation.cs

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace WcfOperation
{
// 注意: 如果更改此处的接口名称“IService1”,也必须更新 App.config 中对“IService1”的引用。
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(ICallback))] //回调是服务级的属性配置
public interface IOperation
{
//请求应答模式-客户端以消息形式发出请求,它会阻塞客户端直到从服务端收到应答消息
//除NetPeerTcpBinding和NetMsmqBinding外,其余都支持该模式
[OperationContract]
void RequestReply(string str); //注意,调用方是客户端,所以请求是客户端请求

[OperationContract]
// [OperationContract(SessionMode = SessionMode.Required)] //这种情况仍然会阻塞客户端直到得到应答
void OneWayMode(string str); //同样,客户端以单向模式向服务发出请求,而不需要阻塞客户端以等待应答消息
//回调模式 - 指该协议支持将服务端的调用返回给它的客户端,客户端必须为回调对象的托管提供易于实现的机制
//具有双向能力的绑定才支持回调,HTTP本质无连接,所以wsHttpBinding和BasicHttpBinding不能用于回调。
//NetTcpBinding和NetNamedBinding支持回调,因为TCP和IPC协议均支持双向通信
//为了让Http支持回调,WCF提供了WSDualHttpBinding,实际是设了2个HTTP通道,一个是客户端到服务端,另一个相反
//一个服务协议最多只能包含一个回调契约。
}

public interface ICallback
{
[OperationContract(IsOneWay
= true)]
void OnCallback();

[OperationContract(IsOneWay
= false)]
string OnCallbackReturnStr(string str);
}
}

Operation.cs

View Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;

namespace WcfOperation
{
//为每个会话创建一个对象.ConcurrencyMode指示是否单线程,多线程,以及可重复调用?什么事可重复调用?
//可重复调用就是来回调来调去。
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class Operation : IOperation, ICallback
{
ICallback callback
= null;
public Operation()
{
//通过构造函数给接口对象赋值,作用是获取调用当前实例的客户端的通道,获取通道能干吗?
callback = OperationContext.Current.GetCallbackChannel<ICallback>();
}

//static List<ICallback> s_callbacks = new List<ICallback>();
public void RequestReply(string str)
{
System.Threading.Thread.Sleep(
10000); //客户端会在10秒后返回操作,10秒前一直保持阻塞
}

public void OneWayMode(string str)
{
#region 服务器调用客户端上的实现
/****将服务器上的方法放到客户端给予实现并给予参数然后给服务器端执行有什么意义呢?****/
//Trace.WriteLine("do sth.");
//MessageBox.Show("服务端OneWayMode方法被执行了!");
callback.OnCallback(); //输出结果是客户端重定义的OnCallback实现的方法,和服务器端的OnCallback实现内容无关
//这一句等同 在客户端icallback.OnCallback()
string strFromClient = callback.OnCallbackReturnStr("服务器:服务端给的字符串!"); //执行结果仍然是客户端所定义的实现
MessageBox.Show("服务器得到函数在客户端执行后返回的值"+strFromClient);
#endregion
}


public void OnCallback()
{
//doSth.
MessageBox.Show("服务端的回调函数!");
}

public string OnCallbackReturnStr(string str)
{
MessageBox.Show(
"服务器:" + str);
return str;

}
}
}

服务端app.config

View Code
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- 部署服务库项目时,必须将配置文件的内容添加到
主机的 app.config 文件中。System.Configuration 不支持库的配置文件。
-->
<system.serviceModel>
<services>
<service behaviorConfiguration="WcfOperation.Service1Behavior"
name
="WcfOperation.Operation">
<endpoint address="" binding="wsDualHttpBinding" bindingConfiguration=""
contract
="WcfOperation.IOperation">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/WcfOperation/Operation/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfOperation.Service1Behavior">
<!-- 为避免泄漏元数据信息,
请在部署前将以下值设置为 false 并删除上面的元数据终结点
-->
<serviceMetadata httpGetEnabled="True"/>
<!-- 要接收故障异常详细信息以进行调试,
请将下值设置为 true。在部署前
设置为 false 以避免泄漏异常信息
-->
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>

客户端调用代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using TestWcfOperation.ServiceReference1;
using System.Windows.Forms;
using System.Diagnostics;

namespace TestWcfOperation
{
class Program
{
static void Main(string[] args)
{
//ServiceReference1.OperationClient sc = new OperationClient(); //如果没有定义服务契约上的回调协议
//我服务器端名字起的叫ICallback这边怎么不是的呢?这又没有影响?
// IOperationCallback icallback = new ServiceReference1.IOperationCallback(); //错误,因为无法创建接口(或者抽象类)的实例

IOperationCallback icallback
= new InstanceIOperationCallback(); //创建一个集成了A接口的的类的实例=同A接口的实例?
InstanceContext context = new InstanceContext(icallback); //参数要求是一个接口的实例,怎么办呢?如何实例化一个接口?
OperationClient sc = new OperationClient(context); //参数要求是一个回调上下文类型的实例
sc.OneWayMode("客户端调用!"); //此时,调用OneWayMode方法时回调函数OnCallback有没有被执行呢?
//结果是OnCallback()并没有发生,为什么呢?如何才能引发呢?
// icallback.OnCallback(); //这样调用的话是客户端的函数,和普通函数调用没两样,不涉及回调
//sc.OneWayMode("客户端再次调用!");
Console.ReadLine();
}

public class InstanceIOperationCallback : IOperationCallback //用类来实例化一个接口类型
{
public void OnCallback()
{
//是否重写随便你
MessageBox.Show("这个是在客户端重写的回调函数的随便的内容!");
}

public string OnCallbackReturnStr(string str)
{
str
= "客户端:客户端所给的值!";
MessageBox.Show(str);
return "客户端处理过了:"+str;
}
}


}
}
posted on 2011-02-15 20:36  人的本质是什么?  阅读(524)  评论(0编辑  收藏  举报