技术开发 频道

WCF操作、回调与重入


   单调服务与单例服务非常适合使用这种方式维持回调对象引用。会话服务则没有必要。“但是,如果会话服务为了让其它宿主端或跨会话访问,而将它的回调引用保存在某个全局变量中,就必须添加Disconnect()方法,以达到移除回调引用的目的,因为在调用Dispose()期间不能使用回调引用。”

   DuplexClientBase<T>类并没有为回调契约提供类型安全性,也没有对服务契约与回调契约之间的约束关系进行验证。因此,本书还提供了DuplexClientBase<T,C>类,通过反射、泛型等技术对其提供类型安全。

   与ChannelFactory<T>类相似,WCF同样提供了DuplexChannelFactory<T>类,它被用于通过编程方式设置双向代理。同样的,DuplexChannelFactory<T>类仍然缺乏对回调契约的类型安全。因此,本书提供了DuplexChannelFactory<T,C>类,可以弥补DuplexChannelFactory<T>类的不足。 

   回调契约仍然具有继承的层级。书中讲述了很多,其实一言以蔽之,就是要求回调契约的层级与服务契约的层级保持一致。此外,服务自身还可以实现回调契约。

   由于使用WSDualHttpBinding绑定执行回调时,需要开通两个HTTP通道,一个用于服务,一个用于回调。通常,WCF为回调通道选择了默认的80端口,但如果客户端运行了IIS,则可能会占用80端口,就会导致端口的冲突。实际上,我们可以为回调通道指定任何可用的端口,例如,我们可以通过配置文件为客户端指定基地址。然而,我们指定的端口仍然可能会被占用,只是这种占用的可能性比80端口小。为了避免潜在的端口冲突,同时简化程序员的工作,最好的办法是自动分配一个可用的端口。本书定义了WsDualProxyHelper静态辅助类,能够将客户端基地址设置为任意的可用端口。定义如下:
public static class WsDualProxyHelper 
{
public static void SetClientBaseAddress<T>(DuplexClientBase<T> proxy,int port)
where T : class
{
WSDualHttpBinding binding = proxy.Endpoint.Binding as WSDualHttpBinding;
Debug.Assert(binding != null);
binding.ClientBaseAddress = new Uri("http://localhost:"+ port + "/");
}
public static void SetClientBaseAddress<T>(DuplexClientBase<T> proxy)
where T : class
{
lock(typeof(WsDualProxyHelper))
{
int portNumber = FindPort( );
SetClientBaseAddress(proxy,portNumber);
proxy.Open( );
}
}
internal static int FindPort( )
{
IPEndPoint endPoint = new IPEndPoint(IPAddress.Any,0);
using(Socket socket = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp))
{
socket.Bind(endPoint);
IPEndPoint local = (IPEndPoint)socket.LocalEndPoint;
return local.Port;
}
}
}
   WsDualProxyHelper类的使用如下所示:
class MyClient : IMyContractCallback 
{...}

IMyContractCallback callback = new MyClient( );
InstanceContext context = new InstanceContext(callback);

MyContractClient proxy = new MyContractClient(context);

WsDualProxyHelper.SetClientBaseAddress(proxy);
0
相关文章