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

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


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

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

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

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

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

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


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

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

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

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

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

 Не удалось загрузить файл или сборку "ServiceApp, Version=1.0.0.0, Culture= нейтральный, PublicKeyToken=null" или одну из его зависимостей. Система не может найти указанный файл. 

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

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

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

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

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

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

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

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

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

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

 Средство форматирования выдало исключение при попытке десериализации сообщения: при попытке десериализации параметра http://tempuri.org/:msg произошла ошибка. Сообщение InnerException было "Элементом XML", "http://tempuri.org/:msg" не содержит ожидаемого атрибута "http://schemas.microsoft.com/2003/10/Serialization/:Type". Десериализатор не знает, какой тип десериализовать. Убедитесь, что сериализуемый тип имеет тот же контракт, что и десериализованный тип. '. Пожалуйста, смотрите InnerException для более подробной информации. 

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

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


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

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

5 ответов

Решение

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

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

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

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

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

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

Использовал оба.

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

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

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

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

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

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

Вот один шаблон, чтобы сделать Remoting-подобные вещи с WCF:

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

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

Другие вопросы по тегам