Remoting или WCF для новой разработки (между двумя приложениями .NET на одной машине) с использованием интерфейсов? - PullRequest
11 голосов
/ 21 сентября 2009

Мы хотим, чтобы два приложения .NET, работающие на одном компьютере, общались друг с другом.Мы хотим три проекта.Библиотека, содержащая интерфейсы.Приложение «сервер», которое реализует интерфейсы, и приложение «клиент», которое взаимодействует с сервером с помощью интерфейсов.Мы не хотим, чтобы клиент ссылался на сервер.
У нас есть тестовое приложение, которое делает это с удаленным взаимодействием, но недавно обнаружило, что удаленное взаимодействие заменяется на WCF.Поскольку это новая разработка, мы считаем, что нам следует использовать WCF, но нам не удалось заставить ее работать с WCF, и мы задавались вопросом, возможно ли это?


РЕДАКТИРОВАТЬ:

Извините за нехватку деталей выше, но у меня не было доступа к коду в то время.Я работаю с двумя другими людьми над этим проектом и не пристально смотрю на их вещи IPC.Я знаю, что в настоящее время они придерживаются мнения, что WCF не может делать то, что они хотят, и я надеюсь, что смогу показать им, что он может.

Я начал смотреть на попытки моих коллег в этоми буду продолжать обновлять этот пост, насколько я понимаю.

Ниже приведена упрощенная версия их тестового кода для удаленного взаимодействия.Они хотят сделать это с помощью WCF, но до сих пор не смогли заставить его работать.

Обе сборки ServiceApp и ClientApp ссылаются на сборку Lib.Они не ссылаются друг на друга.

Я отредактирую это снова, когда смогу лучше объяснить их попытку воспроизвести это поведение в WCF.На данный момент все, что я действительно знаю, это то, что они используют NetNamedPipeBinding и испытывают проблемы с клиентским приложением, жалующимся, что оно не может получить доступ к сборке службы.


РЕДАКТИРОВАТЬ:

Ниже приведенупрощенная версия тестового кода для WCF.

Следующая строка из ClientProgram вызывает исключение:

IMessage msg2 = service.CreateMessage("Hello World");

Вот исключение:

Could not load file or assembly 'ServiceApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

EDIT:

Пытаясь понять последний комментарий Стивена, я прогуглил IMetadataExchange, который, конечно же, впервые попал на MSDN Page .На этой странице говорилось:

Нет необходимости реализовывать контракт MetadataReference в вашей реализации сервиса.Вместо этого добавьте ServiceMetadataBehavior в описание службы.

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

Подробнее о публикации метаданных в WCF см. Публикация метаданных .

Потому что в этом примере я не использую файлы конфигурации, а вместо этого выбираю ссылку Publishing Metadata .Оттуда я перешел по ссылке Как: опубликовать метаданные для службы с использованием кода , в которой был хороший пример, который я использовал для изменения кода приложения-службы *1102*.Добавленный код находится в строках 15-20.

Мне удалось добавить ссылку на сервис после небольшой работы. Служба должна быть запущена, но если вы запускаете ее через Visual Studio, у вас нет возможности добавить ссылку на службу. Кроме того, я до сих пор не понимаю, как должна работать опция «Обнаружение служб в решении». В конце я смог добавить ссылку, открыв папку bin / debug, чтобы вручную запустить службу, а затем введя URL-адрес, который я добавил в приложение-службу. Если это правильный путь, то довольно неловко.

После всего этого код , сгенерированный , с тех пор не делает ничего для меня. Во-первых, он воссоздает мой интерфейс IService, но превращает все мои сообщения в объекты и украшает их немного по-другому. Если их интерфейс используется, то он не только будет использовать другой сервис IService, чем фактически реализует мой сервис, но методы в этом сервисе даже не имеют одинаковые подписи!

Откладывая это в сторону, я предполагал, что мне придется изменить свой клиент, чтобы использовать объекты из вновь созданного объекта, поэтому я изменил свой код клиента .

Теперь, когда я пытаюсь запустить его, в строке 4 появляется следующая ошибка:

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:msg. The InnerException message was 'XML 'Element' 'http://tempuri.org/:msg' does not contain expected attribute 'http://schemas.microsoft.com/2003/10/Serialization/:Type'. The deserializer has no knowledge of which type to deserialize. Check that the type being serialized has the same contract as the type being deserialized.'.  Please see InnerException for more details.

EDIT:

Один день остался за вознаграждением, а ответов нет, так как я добавил вознаграждение. Есть ли что-то, что я могу уточнить, прежде чем истечет время щедрости?


EDIT:

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

Ответы [ 5 ]

18 голосов
/ 21 сентября 2009

WCF - это путь, в частности, проверьте привязку Net Named Pipe к WCF. Это позволит очень быстрое межпроцессное взаимодействие на одном компьютере.

Если вы ориентируетесь на Windows Server 2008 для производственного развертывания, вы можете использовать IIS 7 в качестве среды размещения. Проверьте Расширение услуг WCF за пределы HTTP с WAS .

Есть много WCF, начинающих информацию о типах там. Проверить:

Если у вас возникли проблемы с началом работы, то опубликуйте какие-либо конкретные ошибки или примеры, возможно, вы продемонстрировали это, и я уверен, что кто-то здесь может помочь!

4 голосов
/ 21 сентября 2009

Используются оба.

Определенно идите с WCF.

Remoting плохо документирован и обидчив. WCF намного проще в сравнении. Не уверен, что у вас проблемы, но на WCF есть множество документов.

3 голосов
/ 21 сентября 2009

Я только что переключил программу с удаленного взаимодействия на WCF, и я столкнулся с множеством вещей, которые раньше беспрепятственно работали в удаленном взаимодействии, но это вызывает проблемы в wcf:

  • Класс CallContext исчез. Я использовал это для передачи некоторой информации о напр. текущий выбранный язык и некоторая информация о пользователе. В WCF мне пришлось создать MessageInspector, чтобы добавлять заголовки с этой информацией к каждому запросу.
  • Исключения больше не передаются без изменений. Вместо этого вам нужно использовать FaultException и FaultContracts.
  • Прокси не кажутся такими легкими. Мне нужно избавиться от них, а не просто оставить их для сбора мусора, иначе мой сервис будет зависать. (На самом деле это даже не так просто, как вызов Dispose для корректного завершения прокси, вам нужна довольно сложная последовательность try, catch, наконец, которая вызывает Close и Abort для разных типов исключений.) Необходимость закрытия прокси вызывает немного проблемы, когда я хочу, чтобы моя среда IoC управляла прокси-серверами.

Я не говорю, что вы должны использовать Remoting, я просто говорю, что есть причины также рассмотреть Remoting. Определенно проще настроить и приступить к работе.

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

3 голосов
/ 21 сентября 2009

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

Обычный способ сделать что-то в WCF - создать общую сборку, состоящую полностью из объектов передачи данных (все свойства, без кода) и интерфейсов. Обе стороны ссылаются на эту сборку, но клиент использует сервисную ссылку сервера. Это помогает?

1 голос
/ 01 октября 2009

Вот один шаблон для выполнения Remoting-подобных вещей с WCF:

  • 3 проекта: сервер, клиент, shared.dll
  • сервер и клиент оба ссылаются на shared.dll
  • поместить интерфейс службы с [ServiceContract] в shared.dll
  • поместить класс реализации сервиса на сервер
  • не используйте интерфейсы для ваших типов данных
  • создание базовых типов DataContract с использованием только той логики, которую вы хотите разделить между клиентом и сервером (например, проверка)
  • помещает ваши типы данных DataContract в shared.dll
  • Не используйте NetDataContractSerializer (как вы, кажется, делаете в своем коде)

Конечно, есть вариации на эту тему. Например. вместо разделяемой dll вы можете обмениваться файлами кода между проектами сервера и клиента с #if для различной компиляции.

...