2012-03-29 5 views
2

Я проектирую службу WCF с обратным вызовом, но моя реализация функции обратного вызова никогда не вызывается. И я смущен про созданный сервисный прокси, поэтому, пожалуйста, помогите.Функция реализации обратного вызова WCF никогда не называется

Вот сценарий: на стороне сервера я определил сервисный интерфейс IMyService и интерфейс обратного вызова IMyServiceCallback, я также реализовал IMyService в проекте сервера. Помимо проекта сервера, у меня наверняка есть другой клиентский проект, к которому я добавил ссылку на службу в VS. И я реализовал интерфейс IMyServiceCallback на стороне клиента. Поэтому возникает проблема: когда я отлаживаю ее, функция никогда не входит в мою реализацию IMyServiceCallback, и, конечно же, желаемый результат никогда не выйдет.

И это я, где я запутался: когда я добавил ссылку на службу на стороне клиента, она фактически создала три интерфейса на локальном компьютере: IMyService, IMyServiceCallback и IMyServiceChannel плюс клиентский прокси-класс. И в моей локальной реализации IMyServiceCallback я объявил класс реализовать локальный интерфейс IMyServiceCallback, а не тот, который со стороны сервиса. Это может быть проблема? Почему существуют два объявления интерфейса в разных проектах (и, следовательно, разные пространства имен)? Причина, по которой я реализую интерфейс на стороне клиента, заключается в том, что если бы я реализовал интерфейс на стороне сервера, это дало бы ошибку: «Экземпляр InstanceContext, предоставленный ChannelFactory, содержит объект UserObject, который не реализует ошибку CallbackContractType», когда я пытался позвонить службе. И еще одна запутанная часть - на стороне сервера, если я объявляю имя интерфейса обратного вызова как IMyCallback или что-то еще, вместо IMyServiceCallback, сгенерированный интерфейс на стороне клиента все равно будет IMyServiceCallback, который является именем сервисного интерфейса плюс суффикс «Обратный звонок». И в этой ситуации я также получил «InstanceContext, предоставленный ChannelFactory, содержащий объект UserObject, который не реализует ошибку CallbackContractType».

Я думаю, что я неправильно понял о «добавлении ссылки на службу» и о том, как я должен реализовать интерфейс (какой из них реализовать). Может ли кто-нибудь мне помочь? Благодаря!

Обновлено:

Я как-то исправил проблему. Во-первых, желательны две декларации. Локальному клиенту потребуется реализовать локальный интерфейс, который создается при добавлении ссылки на службу. И моя проблема заключалась в том, что я также определил DataContract, но у сгенерированного ссылочного файла этого не было. Это может быть связано либо с тем, что я добавил сборку сервисного проекта в качестве ссылки (кто-то сказал, что в этом случае ссылка на службу не будет генерировать Datacontract) или потому, что мне не хватает атрибута DataMember. Но так или иначе, после того, как я исправил обе части, функция работает сейчас.

ответ

2

Когда вы добавляете ссылку на службу и генерируете прокси-сервер, он полностью отделен от вашей реализации службы. Помните, что вы можете использовать службу, которую вы не написали, и не имеете доступа к исходному коду службы.

Клиентский код должен использовать клиентские интерфейсы. Если вы меняете свою услугу, вам необходимо восстановить прокси-сервер.

Если вы считаете это слишком грязным, и вы знаете, что всегда будете контролировать оба конца, вы можете совместно использовать служебные интерфейсы в общей сборке и генерировать прокси-класс во время выполнения с использованием DuplexChannelFactory.CreateChannel().

Что касается вашей проблемы, я могу только предположить, что вы неправильно регистрируете обратный вызов. Это покрыто here.

+0

Спасибо за ответ. Как я уже упоминал об обновлении моего первоначального сообщения, теперь я заметил, что желательно объявление локального интерфейса. И имеет смысл, что я «могу потреблять услугу, которую вы не написали, и не имеете доступа к исходному коду службы». Я думаю, что моя проблема заключалась в одном объявлении DataContract, которое ошибочно не было создано на стороне клиента. – tete

0

Если вы хотите опубликовать, вы должны реализовать IMyServiceCallback и IMyService вместе в одном проекте. , если вы подписались только на подписку, вы должны реализовать интерфейс IMyServiceCallback

+0

Спасибо за ваш ответ. Я только хочу подписаться, и именно поэтому я только реализовал IMyServiceCallback. – tete

0

Я исправил проблему, когда моя команда обратного вызова была встроена в вызов функции. Я узнал, что размещение обратного вызова только методом, который не возвращает результат, отлично работает. Однако, когда команда обратного вызова помещается внутри функции, я столкнулся с проблемой тайм-аута.

я решил его с помощью BackgroundWorker нити внутри функции быть вызвано:

public static IMyServiceCallback Callback; 
. 
. 
. 

     TaskStateData taskStateData = GetSomeData(); 

     BackgroundWorker backgroundWorker = new BackgroundWorker(); 

     backgroundWorker.DoWork += (se, ev) => 
      { 
       Tuple<OperationContext, TaskStateData> data = ev.Argument as Tuple<OperationContext, TaskStateData>; 
       var operationContext = data.Item1; 

       if (operationContext != null) 
       { 
        Callback = operationContext.GetCallbackChannel<IMyServiceCallback>(); 
        Callback.OnCallBack(); 
       } 
      }; 

     Tuple<OperationContext, TaskStateData> payload = new Tuple<OperationContext, TaskStateData>(OperationContext.Current, taskStateData); 
     backgroundWorker.RunWorkerAsync(payload); 
Смежные вопросы