我有一台控制复杂工业系统的服务器。
我们需要编写一个可以连接到服务器并“观察”其内部状态的远程客户端。我需要解决这个问题:
我目前的方法是手工编写代码,监视服务器上每个对象的更改,并将其作为消息发送给客户端。客户端接收这些消息并将这些更改应用于其自己的本地模型。
问题是这涉及大量的手动编码,我为每个实体提供了三个类:服务器,消息和客户端。即使观察州的变化也是相当费力的。
我觉得必须有一个更好,更通用的方法来实现这个目标吗?
顺便提一下,我使用的技术是.net,c#,WPF和WCF
答案 0 :(得分:3)
我要建议的可能很难对现有系统进行改造,但我认为这是一种有效的模式。您可以将其称为“复制模型”。
我的想法是你的服务器有一个模型,客户端应该有一个相同的模型。
服务器模型的所有更新都将作为应用于模型的事件到达。现在,如果这些事件是可序列化的,那么我们也可以将它们发送到客户端,它将看到相同的更新。
我们需要做的就是让客户端和服务器模型的初始状态一步一步。如果我们使Model可序列化也是最简单的。使用时间戳机制,客户端现在可以:
Hey Server, I'd like to to start replicating
服务器
Here's the current snaphot and I'll be sending you all updates after that
这有很多皱纹。例如,如果消息丢失,如何恢复同步。
这里的关键是模型需要与服务器中的其他代码分离。它的类不能引用处理类。相反,如果要触发工作,它必须发出事件。然后在服务器中发生了一些事情,但在客户端中,这些工作事件被简单地忽略了。
这种方法的优点是,一旦你有了复制机器人,那么随着模型的改变,几乎没有维护。如果所有模型类和chnage事件都是可序列化的,则相同的代码在服务器和客户端中运行。
答案 1 :(得分:2)
客户端是否需要了解服务器状态的所有信息?我假设服务器上发生的一些事情并不重要,不需要监控,或者太详细而无法完全监控。因此,客户端将查看服务器状态的摘要,而不是所有内容的完整详细信息。
djna的复制模型是一个好主意 - 服务器上的一组独立的模型类,用于表示需要与客户端共享的状态。这将是服务器完整内部状态的简化摘要。
我想知道服务器上有多少不同的代码片段进行客户需要了解的更改 - 共享模型的更改。如果来自许多地方的更改,您是否可以在模型的顶部放置简化的外观,以控制对它的访问?因此,如果组件A,B,C和D都需要进行更改,则它们都必须通过外观。然后,您可以将事件跟踪逻辑放在外观中,而不是整个模型中。
如果您必须在许多不同的类中进行跟踪,您可以考虑使用面向方面的编程来自动将跟踪代码添加到每个类。 PostSharp是一个很好的工具,可以在编译应用程序时通过向.NET程序集添加代码来实现此目的。
这是一篇关于使用INotifyPropertyChanged界面将PostSharp用于automate change tracking的博文。看起来还有一个名为PropFu的PostSharp插件。
由于您控制两端的代码(触发和使用事件),您不必使用INotifyPropertyChanged - 您可以定义自己的界面,这对您的应用程序更好。但你可以使用类似的方法。
更改跟踪代码可以将事件放入服务器上的内存中队列。客户端可以定期向服务器询问最新事件;然后,服务器将检查此队列并将所有排队的事件发送到客户端。 (您也可以将每个事件实时推送到客户端,但如果它们发生的速度非常快,则可能不实用。)
当客户端连接时,服务器可以像djna所描述的那样向客户端发送快照。从那时起,服务器可以跟踪其队列中的事件。当客户端断开连接时,服务器可能会停止跟踪事件,直到客户端稍后再次连接。当客户端重新连接时,服务器将发送另一个完整快照,然后发送更多事件。
我一直假设客户端只有一个实例。如果不止一个,您需要单独跟踪已发送给每个客户端的事件,并且只要至少连接了一个客户端,您就必须继续跟踪事件。