从客户端应用程序我发送请求/事务(包含执行(和参数)+ transactionID的操作)到远程队列.远程服务器在某个时候将请求出列,并且需要一些时间来处理它.
一旦完成处理它,它就会在客户端队列上发送一个响应(包含应用响应+ transactionID)...所以这是一个完全"断开连接"的通信模式,客户端可以将响应映射到请求是通过transactionID.
消息响应在客户端出列,并与原始请求匹配(基于transactionID).
我现在正在做的是,当客户端将请求发布到服务器队列时,它会向保留transactionId和callback(委托)的字典添加回调.这是一个Dictionary<int, object>将transactionId映射回回调用操作结果调用的回调.
回调/委托存储为对象,因为根据请求,回调委托签名是不同的(例如,响应可以返回a List<string>而另一个响应可以返回int).
当客户端队列使响应出列时,它知道响应的类型(因此知道回调的相应签名),因此它根据transactionID从字典中获取回调.然后它将对象强制转换回相应的委托类型并调用回调.
我发现这种方法不是很"性感",但我并没有真正看到另一种方法来执行这样的任务.
有没有更好的方法来执行此操作?
如果问题不够明确,请告诉我并通过一些编辑进行澄清.
您可能会发现响应式扩展是此类消息传递的便捷工具。
首先,让所有响应实现某个接口或基类,例如 IMessage。每种类型的响应都应该封装在一个单独的类中,如下所示
public interface IMessage
{
int TransactionId { get; }
}
public class UserListMessage : IMessage
{
int TransactionId { get; set; }
public List<string> Users { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
然后让你的消息队列实现IObservable<IMessage>。反应式扩展提供了一个名为 的现成可用的实现Subject<T>,您可能想要包装它或其他东西。
Observable 实现了一种Subscribe(IObserver<IMessage> observer)将观察者存储在内部列表中某处的方法。当新的响应到达时,OnNext(IMessage message)每个订阅的观察者都会调用一个方法。
最后,您的响应处理注册代码可能如下所示:
var subscription = myQueue
.OfType<UserListMessage>()
.Where(msg => msg.TransactionId == id)
.Subscribe(callback);
Run Code Online (Sandbox Code Playgroud)
这将为具有给定事务 ID 的 UserListMessage 类型的消息注册回调。也许您还想在某个地方取消订阅。那将是:
subscription.Dispose();
Run Code Online (Sandbox Code Playgroud)
这是 Rx 的一个简短示例。现在去寻找一些更详细的教程。