Как мне синхронизировать списки в WCF? - PullRequest
2 голосов
/ 25 апреля 2010

У меня есть сервис WCF, который предлагает множество списков элементов разных типов. Списки могут быть изменены на сервере. Каждое изменение должно быть опубликовано для всех клиентов, чтобы у каждого клиента была актуальная копия каждого списка серверов.

В настоящее время я использую эту стратегию: при входе в систему каждый клиент получает текущий статус каждого списка. При каждом изменении добавленный или удаленный элемент отправляется всем клиентам с использованием соответствующего метода обратного вызова.

Недостатком является то, что мне нужно создать новый метод обратного вызова для каждого списка, поскольку элементы имеют разные типы и не могут быть отправлены с использованием одного метода обратного вызова. Есть шаблон, который я мог бы применить? Или мне действительно нужно дублировать код для каждого из списков?

Редактировать: Списки могут часто меняться, поэтому я бы предпочел не присылать весь список при каждом изменении. Вместо этого я просто отправляю измененный товар.

(Edit2: незначительные уточнения)

Ответы [ 2 ]

2 голосов
/ 26 апреля 2010

На основе вашего ответа предоставьте метод, который принимает строку, в которой указывается имя списка, на который клиент хотел бы подписаться. Управляйте списками подписчиков, используя Dictionary<string, List<IWcfCallbackContract>>.

Метод обратного вызова ListChanged должен содержать три аргумента: string listName, ChangeType changeType (где ChangeType - перечисление, указывающее, был ли элемент добавлен, удален или обновлен) и, наконец, object changedItem. Вам также придется использовать ServiceKnownTypeAttribute, чтобы указать, какие типы объектов могут появляться в аргументе changedItem.

Когда элемент в списке изменился, получите всех подписчиков этого списка из объекта Dictionary<> и уведомите каждого с помощью метода ListChanged. Клиент должен привести changedItem из System.Object к тому типу, который он ожидает (согласно списку, указанному в аргументе listName).

0 голосов
/ 25 апреля 2010

Есть одно решение, о котором я могу подумать, но оно кажется немного странным, и я не совсем уверен.

Сервер предлагает общий метод подписки для каждого из списков. Имя списка передается в качестве параметра. При изменении любого списка сервер отправляет имя измененного списка вместе с измененным элементом. Проблема в том, что элемент не может быть передан обычно, потому что в контракте обратного вызова есть только один метод «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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...