我可以使用WCF双工绑定来中继消息吗?

问题描述:

我有一个客户端应用程序,一个服务器和另一个客户端,可以称它为第三方。我有一个回调接口作为我的合同的一部分,由第三方和客户实施。我可以使用WCF双工绑定来中继消息吗?

第三方将调用服务器操作(方法),然后服务器将触发回调,但不调用第三方的回调,它将调用客户端的回调实现。

+1

我在这里没有看到问题。 – 2009-08-04 12:12:45

我想我找到了解决办法..

这里的链接。 http://msdn.microsoft.com/en-us/magazine/cc163537.aspx

试着看图6.这就是我想要实现的。

+0

看看我的例子...我只用一个操作简化了它,但它是相同的模式。 – kyoryu 2009-08-06 10:21:09

从快速阅读的Microsoft Duplex服务文档,我不认为这会做你想做的。可能有其他一些聪明的功夫WCF的方式来做到这一点,但在我的情况下,我为服务器创建了一个“PassThruService”,它实现了与真实服务相同的合同,并将收到的任何请求发送到客户端。

这是我的代码的一部分,它解释了它的主旨。

private const int OPERATION_TIMEOUT = 5000; 
private MyServiceClient m_client = new MyServiceClient(); 

public bool IsAlive() { 
    try { 
     logger.Debug("PassThruService IsAlive."); 

     bool isAlive = false; 
     ManualResetEvent isAliveMRE = new ManualResetEvent(false); 

     m_client.IsAliveComplete += (s, a) => { isAlive = a.Result; isAliveMRE.Set(); }; 
     m_client.IsAliveAsync(); 

     if (isAliveMRE.WaitOne(OPERATION_TIMEOUT)) { 
      return isAlive; 
     } 
     else { 
      throw new TimeoutException(); 
     } 
    } 
    catch (Exception excp) { 
     logger.Error("Exception PassThruService IsAlive. " + excp.Message); 
     throw; 
    } 

我不完全看到你真的在这里问什么....但我会尽量提供一些提示。

在.NET 3.5中的WCF中不能很好地支持中继消息或路由 - 基础架构在那里,但仍然需要大量工作才能手动进行设置。

我知道到在.net 3.5这个话题WCF最好的介绍是由两部分组成的文章由米歇尔·勒鲁布斯塔曼特在MSDN杂志:

部分2在双工路由器上有一个部分 - 是否可以帮助你完成任务?

.NET 4.0中的WCF承诺会为路由带来额外的支持 - 将会有RoutingService基类可以用来编写路由服务,并且它将允许可配置的,基于内容或基于元数据的路由 - 无论它是你需要的。

.NET 4.0计划在今年晚些时候(2009年)的某个时候发布 - 希望!所以虽然这还是未来,但它看起来很好看!

Marc

是的,你绝对可以这样做。

最简单的方法是将您的服务实现为PerSession服务,并在初始化/构建时捕获回调上下文。通常,我会将服务对象(实际上表示此时的连接)添加到内部核心对象。然后,当您接收到来自客户端的消息时,可以调用任何服务对象(而不是通过契约),并在内部将数据转发给关联的客户端。

这是一个相当简单的概念实现,没有异常处理,和一些非常糟糕的设计(静态类BAD!)。我还没有测试过这个,但即使我错过了穿过我或点了一个t的原则,这些原则也应该保留下来。此示例还将呼叫转发给所有客户端,但选择单个客户端时遵循相同的基本模式。

试图用一个单独的服务,这样做会更困难,而且每次呼叫的服务显然是行不通的:)

[ServiceContract(CallbackContract = typeof(ICallback))] 
public interface IContract 
{ 
    [OperationContract(IsOneWay = true)] 
    void SendTheData(string s); 
} 

public interface ICallback 
{ 
    [OperationContract(IsOneWay = true)] 
    void ForwardTheData(string s); 
} 

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerSession)] 
public class ServiceConnection : IContract 
{ 
    private ICallback m_callback; 

    public ServiceConnection() 
    { 
     m_callback = OperationContext.Current.GetCallbackChannel<ICallback>(); 
     ServiceCore.Add(this); 
    } 

    public void SendTheData(string s) 
    { 
     ServiceCore.DataArrived(s); 
    } 

    public void SendToClient(string s) 
    { 
     m_callback.ForwardTheData(s); 
    } 
} 

static public class ServiceCore 
{ 
    static private List<ServiceConnection> m_connections = new List<ServiceConnection>(); 


    public static void DataArrived(string s) 
    { 
     foreach(ServiceConnection conn in m_connections) 
     { 
      conn.SendTheData(s); 
     } 
    } 

    public static void Add(ServiceConnection connection) 
    { 
     m_connections.Add(connection); 
    } 
}