How do I synchronize lists in WCF?
I have a WCF service that offers many lists of items of different types. Lists can be changed on the server. Each change must be published to all clients so that each client has the latest copy of each server list.
I currently use this strategy: upon login, each client gets the current status of each list. Whenever a change is made, the added or removed item is sent to all clients using the appropriate callback method.
The downside is that I have to create a new callback method for each list, since the items are of different types and cannot be dispatched using the same callback method. Is there a sample I could apply? Or do I really need to duplicate the code for each of the lists?
Edit: Lists can change frequently, so I'd rather avoid submitting the entire list on every change. Instead, I just post the changed item.
(Edit2: minor clarifications)
a source to share
Based on your answer, provide a method that takes a string that specifies the name of the list the customer would like to subscribe to. Manage your subscriber lists with Dictionary<string, List<IWcfCallbackContract>>
.
Callback method ListChanged
must contain three arguments string listName
, ChangeType changeType
(wherein ChangeType
- enumeration indicating whether the element is added, deleted or updated), and finally object changedItem
. You will also need to use ServiceKnownTypeAttribute
to specify what types of objects can appear in the argument changedItem
.
When an item in a list has changed, get all the subscribers of that list from the object Dictionary<>
and notify everyone using the ListChanged method. The client should cast changedItem
from System.Object
to whatever type it expects (according to the list given in the argument listName
).
a source to share
There is one solution I could think of, but it feels a little odd and I'm not sure.
The server offers a general subscription method for each of the lists. The name of the list is passed as a parameter. When any list changes, the server sends the name of the changed list along with the changed item. The problem is that the item cannot be passed in normally because the callback contract only has one ListWasChanged method (I absolutely want to avoid using a new callback method for each of the lists, see question).
However, this can be resolved by passing in the modified element, serialized as a string. By using the NetDataContractSerializer, the client can easily recover the serialized item and pass it to the correct handler for each list.
What do you think about this? Is it possible? At first I thought it was too much of a performance hit, but on the other hand, we still have to serialize each item. The only added performance hit is string serialization, which shouldn't be too big.
Since this may seem a little confusing, here is a pseudocode implementation:
Server:
// let 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);
}
}
a source to share