我有一个WCF服务,它提供了许多不同类型的项目列表。可以在服务器上更改列表。必须将所有更改发布到所有客户端,以确保每个客户端都有每个服务器列表的最新副本。
目前我正在使用此策略:登录时,每个客户端都会收到每个列表的当前状态。在每次更改时,使用相应的回调方法将添加或删除的项目发送给所有客户端。
缺点是我必须为每个列表创建一个新的回调方法,因为这些项是不同类型的,不能使用单个回调方法发送。有可能适用的模式吗?或者我真的必须为每个列表重复代码吗?
编辑:列表可能会经常更改,因此我宁愿避免在每次更改时发送整个列表。相反,我只是发送更改的项目。
(Edit2:minor clarifiactions)
答案 0 :(得分:2)
根据您的回答,提供一个接受字符串的方法,该字符串指定客户端要订阅的列表的名称。使用Dictionary<string, List<IWcfCallbackContract>>
管理订阅者列表。
ListChanged
回调方法应该包含三个参数:string listName
,ChangeType changeType
(其中ChangeType
是一个枚举,指定项目是否已添加,删除或更新),最后object changedItem
。您还必须使用ServiceKnownTypeAttribute
来指定changedItem
参数中可以显示的对象类型。
当列表中的项目发生更改时,从Dictionary<>
对象获取该列表的所有订阅者,并使用ListChanged方法通知每个订阅者。客户端应该将changedItem
从System.Object
转换为它所期望的任何类型(根据listName
参数中指定的列表)。
答案 1 :(得分:0)
有一个我能想到的解决方案,但感觉有点奇怪,我不太自信。
服务器为每个列表提供通用订阅方法。列表的名称作为参数传递。在更改任何列表时,服务器将更改的列表的名称与更改的项目一起发送。问题是,项目通常无法传递,因为回调契约只有一个“ListWasChanged”方法(我绝对想避免为每个列表设置一个新的回调方法,请参阅问题)。
但是,这可以通过将已更改的项目序列化为字符串来解决。通过使用NetDataContractSerializer,客户端可以轻松地重建序列化项目并将其传递给每个列表的正确处理程序。
你怎么看待这个?这可行吗?起初我认为这会严重损害性能,但是第二个想法,无论如何我们必须序列化每个项目。唯一增加的性能命中是字符串的序列化,这不应该太多。
由于这听起来有点混乱,这里是伪代码的实现:
服务器:
// let's call it SyncList - a list that sends updates on changes
class SyncList<T> : List<T>
{
// this is called on every change of the list
void OnListChanged<T (string name, T item)
{
// serialize the item
string ser = NetDataContractSerializer.Serialize(item);
// send the item together with the name of the list
WcfCallbackChannel.ListChanged (name, ser);
}
}
客户端:
// this stores each of the lists
Dictionary<string, List<T>> _Lists;
// the list callback implementation
class WcfCallbackImplementation : IWcfCallbackContract
{
// called on every change of ANY list
void ListChanged (string name, string item)
{
// get the item back
var item = NetDataContractSerializer.Deserialize (item);
// add/remove/update item
_Lists[name].Add (item);
}
}