How should I synchronize lists in WCF?
I've got a WCF service that offers many lists of items of different types. The lists can be changed on the server. Every change has to be published to all clients to make sure every client has an up-to-date copy of each server list.
Currently I'm using this strategy: On login, every client receives the current status of every list. On every change, the added or removed item is sent to all clients using the respective callback method.
The drawback is that I have to create a new callback method for every list, since the items are of different types and cannot be sent using a single callback method. Is there a pattern I could apply? Or do I really have to duplicate code for each of the lists?
Edit: The lists may be changed frequently, so I'd prefer to avoid to send the whole list on each change. Instead, I'm just sending the 开发者_如何学Gochanged item.
(Edit2: minor clarifiactions)
Based on your answer, provide a method that accepts a string which specifies the name of the list the client would like to subscribe to. Manage the subscriber lists using a Dictionary<string, List<IWcfCallbackContract>>
.
The ListChanged
callback method should contain three arguments: string listName
, ChangeType changeType
(where ChangeType
is an enumeration specifying whether the item was added, removed or updated) and lastly object changedItem
. You will also have to use the ServiceKnownTypeAttribute
to specify what types of objects can appear in the changedItem
argument.
When an item in a list has changed, get all the subscribers of that list from the Dictionary<>
object, and notify each one using the ListChanged method. The client should cast the changedItem
from System.Object
to whatever type it expects (as per the list specified in the listName
argument).
There is one solution I could think of, but it feels a bit weird and I'm not really confident.
The server offers a generic subscription method for each of the lists. The name of the list is passed as parameter. On a change of any list, the server sends the name of the changed list together with the changed item. The issue is, the item could not be passed usually, because the callback contract has only a single "ListWasChanged" method (I absolutely want to avoid having a new callback method for each of the lists, see question).
However, this can be solved by passing the changed item serialized as string. By using NetDataContractSerializer, the client can easily reconstruct the serialized item and pass it to the correct handler for each list.
What do you think of this? Is this feasible? At first I thought this hurts the performance too badly, but on second thought, we have to serialize each item anyway. The only added performance hit is the serialization of the string, which should not be too much.
Since this may sound a bit confusing, here's an implementation in pseudo code:
server:
// 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);
}
}
client:
// 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);
}
}
精彩评论