WCF MessageContract Inheritance - PullRequest
       17

WCF MessageContract Inheritance

5 голосов
/ 24 августа 2009

Я довольно новичок в WCF и у меня просто вопрос, как правильно заставить работать наследование MessageContract. Упрощенная версия моей настройки выглядит следующим образом: «базовый» тип сообщения, а затем еще одно «тестовое» сообщение, которое наследуется от него.

[MessageContract]
public abstract class BaseMessage
{ }

[MessageContract]
public class TestMessage : BaseMessage
{ }

У меня асинхронный OperationContract для ServiceContract определен как:

[OperationContract(AsyncPattern = true)]
IAsyncResult BeginFindRequest(BaseMessage request, AsyncCallback callback, object asyncState);

Проблема, которую я получаю, заключается в том, что при вызове метода BeginFindRequest и передаче экземпляра TestMessage для параметра запроса платформа WCF десериализует экземпляр TestMessage в BaseMessage на стороне службы / сервера. Поскольку это определяется как абстрактный класс, это приводит к следующей ошибке:

"Сообщение не может быть десериализовано в MessageContract типа BaseMessage поскольку он не имеет значения по умолчанию (без параметров) конструктор. "

Из ограниченной информации, которую я могу найти о наследовании MessageContract, кажется, что он должен просто работать.

Итак, мой вопрос - что мне не хватает, чтобы заставить это работать; или, может быть, мне лучше определить отдельный OperationContract для ServiceContract специально для этого типа - недостаток в том, что я мог бы получить много дополнительных OperationContracts?

Ответы [ 5 ]

6 голосов
/ 24 августа 2009

В конце концов я нашел этот пост, который ударил по голове -

К сожалению, способ, который заключает контракт выражены в WCF делает очень Легко забыть, какова их цель: определить сообщения, отправленные на операция и отправляется обратно из операция. На самом деле вы должны подумайте «как бы я выразил эти данные в XML? ». XML не поддерживает наследство так что бы вы ни положили в Контракт будет иметь некоторые способ отображения в XML. Данные контракты, используемые для определения сообщений это просто .NET типизированное удобство для генерации XML для данных Вы хотите пройти - если вы их просматриваете любой другой способ, которым вы предназначены для Мир боли. Вот и думай о данных хочешь сдать, а не как может быть представленным в вашем бизнес-слой и дизайн вашего DataContracts соответственно.

http://www.dotnetconsult.co.uk/weblog2/PermaLink,guid,a3775eb1-b441-43ad-b9f1-e4aaba404235.aspx

Так что я буду рефакторинг, чтобы предоставить дополнительный метод с явным типом контракта. Это также позволит мне очистить реализацию службы, удалив все проверки типов.

Спасибо за помощь.

3 голосов
/ 24 августа 2009

ОК, первый вопрос: почему вы действительно используете контракты на сообщения? Вы действительно нуждаетесь в этом ??

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

"Нормальному" вызову WCF вряд ли когда-либо понадобится использовать контракт сообщений.

Вы определяете ваши сервисные вызовы (методы вашего сервиса), используя [ServiceContract], а структуры данных передаются как [DataContract]. Если у вас есть DataContract, у вас есть больше вариантов того, как обращаться с наследованием / полиморфизмом в вашем сервисе (больше, чем с конструкцией контракта сообщения).

Марк

0 голосов
/ 24 августа 2009

Попробуйте украсить [ServiceContract] атрибутом KnownType . Поскольку TestMessage не является «видимым» из публичной операции, это помогает сантехнику знать, как обращаться с ним, когда он его видит.

Если это позволит сериализировать [DataContract] как TestMessage , вам все равно, вероятно, придется обрабатывать несколько сообщений по-разному с помощью is a или другого преобразования.

0 голосов
/ 24 августа 2009

Ошибка просто хочет, чтобы у вас был пустой конструктор по умолчанию, который он может использовать. Тем не менее, я согласен с marc_s; в проектах, над которыми я работал, я редко использовал контракт сообщений, единственный случай, который я запомнил, был частью службы передачи файлов, где фрагменты файлов передавались в сообщениях.

0 голосов
/ 24 августа 2009

Можно ли изменить BaseMessage так, чтобы это был конкретный класс с конструктором без параметров?

Сообщение об ошибке говорит о том, что невозможно инициализировать объект типа BaseMessage, поскольку он является абстрактным.

...