【问题标题】:Communication between WCF servicesWCF 服务之间的通信
【发布时间】:2013-04-10 09:03:36
【问题描述】:

我正在将服务构建到现有应用程序中,其中构建每个服务的目的是仅由一个客户端使用,并且客户端和服务器设置有双工通信通道。

限制

  1. 我没有重新设计现有基础架构的选项
  2. 我无法使用可共享会话

要求:

  1. 我需要能够在客户端服务之间进行通信(例如,如果用户单击一个项目并想要共享该项目,那么无论出于何种原因,客户端可能无法处理“共享”功能并且需要将其传递给另一个客户端来处理 - 这必须通过服务来完成)
  2. 客户端之间的通信必须由服务进行。

为了让这个最初工作,我直接在两个客户端之间设置了一个 IPC 通道 (netNamedPipeBinding),但我被告知通过服务器发送所有内容。在大多数情况下,这种情况下的“服务器”与客户端运行在同一台机器上,所以我想出了这个非常粗略的概念验证尝试(见下面的代码块)。

问题:当为订阅服务调用方法时,当前服务(在其中调用方法)的操作上下文为空 - 这使得服务无法回调客户端

我正在考虑使用 Juval Löwy 在他的 ServiceModelEx 框架中提供的发布/订阅框架,但是当所有客户端已经在他们自己和各自的服务之间建立了双工通信设置时,这似乎是不必要的......所以目的只是为了添加一个简单的发布/订阅层,该层在概念上位于这些服务的“下方”,并且可以与任何愿意订阅的服务对话。

欢迎提出建议和建设性批评!


    public static class SubscriptionManager<TEventArgs> 
    where TEventArgs : class
{
    private static ConcurrentDictionary<int, Action<TEventArgs>> _subscribers =
       new ConcurrentDictionary<int, Action<TEventArgs>>();

    // sessionId is NOT the WCF SessionId
    public static void FireEvent( int sessionId, TEventArgs eventArgs ) 
    {
        var subscribers = _subscribers.Where( s => s.Key == sessionId );
        var actions = subscribers.Select( keyValuePair => keyValuePair.Value );

        foreach ( var action in actions )
            action.BeginInvoke( eventArgs, action.EndInvoke, null );
    }

    public static void Subscribe(int sessionId, Action<TEventArgs> eventHandler)
    {
        _subscribers.TryAdd(sessionId, eventHandler);
    }

    public static Action<TEventArgs> Unsubscribe(int sessionId)
    {
        Action<TEventArgs> eventHandler;
        _subscribers.TryRemove(sessionId, out eventHandler);
        return eventHandler;
    }
}

【问题讨论】:

  • 你能把你的问题格式化一下吗?难以阅读。
  • 完全有效 :) ... 正在开会... 将很快重新格式化
  • 重新格式化(添加其余部分以满足我现在已经完成的最低字符要求)
  • 根据我的经验,WCF 双工绑定充其量是复杂的。我总是尽量避免使用它们。
  • 如果我有能力改变现有的实现

标签: .net wcf c#-4.0 servicemodelex


【解决方案1】:

首先,我正在实施的模式似乎可以归类为Mediator Pattern

所以我通过传入 FireEvent 调用服务的当前实例上下文来解决这个问题,在我的情况下,它应该与订阅服务的上下文相同。

我在这里处理的情况是断开连接的客户端应用程序,它们在同一用户的上下文中并来自同一台客户端计算机,但(根据要求)它们必须通过服务层进行通信。

我开始使用 WCF 同步上下文和 Juval Lowy 的 ThreadPoolBehavior 类(来自他的 ServiceModelEx 库),但我与 Ninject WCF Extensions 的实现相关联。

所以这个解决方案必须根据你自己的实现进行调整,但是为了让你了解我是如何让它工作的,这里是我更新的FireEvent 方法的要点:

public static void FireEvent( int sessionId, TData eventData, InstanceContext context )
{
    var subscribers = Subscribers.Where( s => s.Key == sessionId );

    var eventArguments = subscribers.Select( kvp => kvp.Value );

    foreach ( var argument in eventArguments )
    {
        // set data associated with the event
        argument.SetData( eventData );

        NinjectInstanceProvider instanceProvider = null;
        Object instance = null;

        try
        {
            // get a "synchronized instance" of the service of type defined by event args
            instanceProvider = new NinjectInstanceProvider( argument.ServiceType );
            instance = instanceProvider.GetInstance( context );

            // get the method from our "synchronized instance"
            // filter by argument types so we don't run into any issues with ambiguity
            var argumentTypes = new[] { typeof ( TEventArgs ) };
            var method = instance.GetType().GetMethod( argument.Callback, argumentTypes );

            // our method arguments
            var arguments = new object[] { argument };

            // invoke the method on our "synchronized instance"
            method.Invoke( instance, arguments );

            // release the instance
            instanceProvider.ReleaseInstance( context, instance );
        }
        catch
        {
            // log
        }
        finally
        {
            if( provider != null )
            {
                if( instance != null ) { instanceProvider.ReleaseInstance( context, instance ); }
            }
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-24
    • 2011-01-10
    • 1970-01-01
    • 2012-06-05
    • 2010-09-29
    • 1970-01-01
    相关资源
    最近更新 更多