Я подумал, что опубликую свой подход, отдавая должное и Грегу, и Джейку за помощь в руководстве по этому пути.
Несмотря на то, что Джейк прав, десериализация данных на клиенте может быть выполнена с любым типом, если он реализует один и тот же контракт данных, однако принудительное выполнение этого без WSDL может быть немного сложным. Я нахожусь в среде, где другие разработчики будут работать с моим решением как для поддержки и поддержки существующих, так и для создания новых клиентов, которые используют мой сервис. Они используются для «добавления справочника услуг» и собираются.
Наиболее полезными были замечания Грега об использовании разных объектов на клиенте и сервере. Я пытался минимизировать дублирование, разделяя мой уровень домена между клиентом и сервером, и это стало причиной моей путаницы. Как только я разделил их на два отдельных приложения и рассмотрел их по отдельности, каждое со своими собственными вариантами использования, картина стала более ясной.
В результате я теперь делюсь сборкой Contracts, которая содержит мои сервисные контракты, так что клиент может легко создать канал к серверу (используя WCF на стороне клиента) и контракты данных, представляющие DTO, передаваемые между клиентом и сервис.
На клиенте у меня есть объекты ViewModel, которые обертывают объекты модели (контракты данных) для пользовательского интерфейса и используют класс агента службы для связи со службой, используя контракты службы из общей сборки. Поэтому, когда пользователь нажимает кнопку «Опубликовать» в пользовательском интерфейсе, контроллер (или команда в WPF / SL) вызывает метод публикации для агента службы, передавая идентификатор документа для публикации. Сервисный агент передает запрос в REST API (операция публикации).
На сервере API REST реализован с использованием тех же сервисных контрактов. В этом случае служба работает с моими доменными службами, репозиториями и доменными объектами для выполнения задач. Поэтому, когда вызывается операция службы публикации, служба извлекает объект домена документа из DocumentRepository, вызывает метод Publish для объекта, который обновляет внутреннее состояние объекта, а затем служба передает обновленный объект в метод Update хранилища. чтобы сохранить изменения.
Я доволен результатом, так как считаю, что это дает мне более надежную и расширяемую архитектуру для работы. При необходимости я могу изменить ViewModels для поддержки пользовательского интерфейса, не беспокоясь о загрязнении службы (служб), и, аналогично, изменить внутреннюю реализацию операций службы (уровень домена), не затрагивая клиентское приложение (я). Все, что связывает их, - это контракты, которые они разделяют. Довольно чисто.