Клиент-сервер через WCF
От: thistle  
Дата: 01.10.09 06:51
Оценка:
Доброго времени суток всем.
Помогите решить проблему при помощи WCF. Есть сервис, на нем хранятся определенные объекты, через контракты к нему подключаются клиенты и меняют значения объектов. Как сделать так, чтобы при изменении объекта одним клиентом его новое значение появлялось у других подключенных клиентов? Сделать необходимо на WCF.
Re: Клиент-сервер через WCF
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 02.10.09 07:18
Оценка: 25 (5)
Здравствуйте, thistle, Вы писали:

T>Доброго времени суток всем.

T>Помогите решить проблему при помощи WCF. Есть сервис, на нем хранятся определенные объекты, через контракты к нему подключаются клиенты и меняют значения объектов. Как сделать так, чтобы при изменении объекта одним клиентом его новое значение появлялось у других подключенных клиентов? Сделать необходимо на WCF.

Сервис определяет контракт и callback-интерфейс для этого контракта.
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IServer
{
...
}


В контракте делаем один из методов с именем Advise, Init или как угодно еще, помечаем его атрибутом [OperationContract(IsInitiating = true)] и метод, который клиент должен вызвать перед окончанием работы с сервисом.

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IServer
{
   [OperationContract(IsInitiating = true)]
   void Advise();
   
   [OperationContract(IsTerminating = true)]
   void Unadvise();

}


Теперь, каждый клиент перед началом работы с твоим сервисом обязан вызвать метод Advise (иначе получит ошибку во время выполнения), в котором сервис сохраняет ссылку на callback-интерфейс подключенного клиента, а перед завершением работы должен вызвать метод Unadvise(), где сервис удалит ссылку на callback-интерфейс соответствующего клиента.

Вот псевдокод метода Advise():
//получаем callback-интефейс текущего контекста
ICallback callBackInterface = OperationContext.Current.GetCallbackChannel<IEquipment>();
//сохраняем этот интерфейс в локальное хранилище
...
//подписываемся на события закрытия канала, чтобы удалить ссылку на интерфейс в случае
//проблем со связью с этим клиентом
OperationContext.Current.Channel.Faulted += EquipmentChannelFaulted;
OperationContext.Current.Channel.Closed += EquipmentChannelClosed;


В методе Unadvise нужно также удалить ссылку на интерфейс, аналогично, как и при потере связи с клиентом.

Поскольку каждая сессия содержит уникальный идентификатор (строковое представление GUID-а), то самым простым способом реализации хранилища, является использование ассоциативного массива по идентификатору сессии.

Теперь в методе сервиса, который изменяет некоторые переменные состояния необходимо уведомить всех клиентов через callback-интерфейс.

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IServer
{
   [OperationContract]
   void FooChanged();
}

[ServiceContract(CallbackContract = typeof(ICallback))]
public interface IServer
{
   [OperationContract(IsInitiating = true)]
   void Advise();
   
   [OperationContract]
   void ChangeFoo(...);

   [OperationContract(IsTerminating = true)]
   void Unadvise();

}


Осталось только на стороне клиента реализовать callback-интерфейс, данные о котором теперь будет публиковаться в метаданных службы.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.