我正在将一个服务构建到一个现有的应用程序中,在这个应用程序中,构建每个服务的目的是只由一个客户端使用它,并且客户端和服务器是使用双工通信通道来设置的。
局限性
要求:
为了开始工作,我在两个客户端之间直接设置了一个IPC通道(netNamedPipeBinding),但是我被告知要通过服务器发送所有东西。这个场景中的“服务器”,在大多数情况下,运行在与客户端相同的机器上,所以我想出了这个概念尝试的粗略证据(参见下面的代码块)。
问题:当为订阅服务调用方法时,当前服务的操作上下文(在其中调用方法)为空--这将使服务无法调用客户端。
我正在考虑使用他在ServiceModelEx框架中提供的Juval L wy的发布/订阅框架,但是当所有的客户已经在他们自己和他们各自的服务之间建立了双工通信设置时,似乎没有必要.因此,其意图只是添加一个简单的发布/订阅层,该层在概念上“位于”这些服务的“下面”,可以与任何愿意订阅的服务进行对话。
欢迎有建设性的意见和批评!
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;
}
}发布于 2013-05-15 17:56:40
因此,首先,我正在实现的模式似乎可以被归类为一个中介模式。
因此,我通过传递FireEvent调用服务的当前实例上下文来解决这个问题,在我的例子中,这个上下文应该与订阅服务的上下文相同。
我在这里处理的情况是在同一个用户和来自同一客户端计算机的上下文中操作的断开连接的客户端应用程序,但是(根据要求)它们必须通过服务层进行通信。
我开始从他的ThreadPoolBehavior库中使用WCF同步上下文和Juval的ServiceModelEx类,但是我被绑定到了一个实现中,Ninject扩展阻碍了它的实现。
因此,这个解决方案必须基于您自己的实现进行调整,但是为了让您了解我是如何让它工作的,下面是我更新的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 ); }
}
}
}
}https://stackoverflow.com/questions/16062786
复制相似问题