2012-05-08 2 views
1

Это мой ABC на стороне сервера:не может сериализовать интерфейсу

<endpoint address="msmq.formatname:DIRECT=OS:.\private$\imhmsgs" 
      binding="msmqIntegrationBinding" 
      bindingConfiguration="IncomingMessageHandlerBinding" 
     contract="TMC.Services.Contracts.Messages.IInboundMessageHandlerService"> 

Как только я сделать .Open() разместить службу, я получаю исключение:

не может сериализовать интерфейс XYZ .Services.Contracts.Messages.Interfaces.IMyMessage.

Мой интерфейс IMyMessage:

[ServiceContract] 
[ServiceKnownType(typeof(IMyMessage))] 
[ServiceKnownType(typeof(ConcreteMessage))] 
public interface IInboundMessageHandlerService 
{ 
    [OperationContract(IsOneWay = true, Action = "*")] 
    void ProcessIncomingMessage(MsmqMessage<IMyMessage> incomingMessage); 
} 

реализатор для этого интерфейса:

[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, 
       ReleaseServiceInstanceOnTransactionComplete = false)] 
public class InboundMessageHandlerService : IInboundMessageHandlerService 
{ 
    [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)] 
    public void ProcessIncomingMessage(MsmqMessage<IMyMessage> incomingMessage) 
    { 
    } 
} 

Тип, который создается клиентом в основном это конкретный класс, который является производным от базового класс, а также интерфейс (IMyMessage), а затем помещает его в MSMQ.

После некоторых тестов, если я удалю атрибуты известного типа сервиса и вместо этого вместо этого произнешу вместо него слово «строка», то, похоже, он открывает хост, но ошибки (потому что тип сообщения не то, что он ожидал).

, где я иду не так?

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

Это не совсем то, чего я ожидал. Как я могу создать его так, чтобы служба могла принимать известный интерфейс и классы, которыми обладает этот интерфейс? Идея заключается в том, что клиент (используя тот же контракт и классы) отправляет сообщение как «IMyMessage», а для службы WCF выбирает «IMyMessage» и далее идет поиск типа сообщения/объекта.

Как?

+0

Оформить эту тему [http://social.msdn.microsoft.com/forums/en-US/wcf/thread/ff81b538-939e-4acf-bef3-40d3677f2f1d]. Это похоже на аналогичную проблему. –

+0

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

+0

на самом деле по какой-то причудливой причине. он работает так, как я хотел в первую очередь ... не знаю, почему и как. * царапины головы * ... поэтому клиент создал конкретные классы, которые получены из базы, из которой реализуется интерфейс.Клиент отправляет класс типа интерфейса - WCF не вызывает проблем, и мы можем проверить тип конкретного класса. Возможно, я добавил, что известные типы в базовом классе, возможно, заставили его «работать» - я не знаю. –

ответ

3

Ваш контракт является интерфейсом, но определение в контракте должно быть конкретным классом.

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

Проблема заключается в том, что когда WCF десериализует то, что было отправлено по проводу, ему необходимо десериализовать его конкретным типом. Если он имеет только интерфейс в определении и 20 различных типов, которые реализуют это определение, он не знает, что с ним делать.

Что вы можете сделать, это иметь базовый тип, который реализует интерфейс, все ваши классы наследуют от базового типа и вы используете базовый тип в вашем контакте.

+0

Спасибо. да, так я работал, пока он не был «сломан», но теперь его магически «фиксированный» .... –

+0

другой тип проекта находится в работе, однако его структура по-разному. Все конкретные классы имеют собственный базовый класс. все базовые классы производятся от 1 основного базового класса. Базовые и конкретные классы - это отдельные проекты. Я могу отправить конкретное сообщение в очередь, но WCF не может десериализоваться. В качестве параметра (mainbase) контракт на обслуживание берет базовый класс. Нет никаких сервисных операций, поскольку это только классы данных (имеет атрибуты datacontract). Любые идеи, в которых я ошибаюсь? Где я должен объявить известные типы? Будут ли они также иметь все базовые типы? –