WCF: использовать пользовательский класс в обратном вызове - PullRequest
3 голосов
/ 21 июня 2011

Мне удалось настроить обратный вызов WCF (через NamedPipes) для работы со строками, но, к сожалению, я не могу заставить его работать с пользовательскими классами.

Вот объявление службы + реализация: http://pastebin.com/Zayi2kjT

вот мой контракт с данными: http://pastebin.com/wFCxrRcJ

вот что я делаю на стороне клиента: http://pastebin.com/jxEbyEtP

Когда я изменяю

    public void Send()
    {
        try
        {
            channel.OnCallback("I love deadlines. I like the whooshing sound they make as they fly by.");
        }
        catch (Exception ex)
        {
            Form1.AddText(ex.GetType() + "|" + ex.Message);
        }
    }

до

channel.OnCallback(new TransmissionClass("I love deadlines. I like the whooshing sound they make as they fly by."));

Я получаю следующее исключение на сервере при вызове метода обратного вызова (см. Выше):

System.ServiceModel.FaultException
Der Formatierer hat beim Deserialisieren der Nachricht eine Ausnahme ausgelöst:   
Fehler beim Deserialisieren von Parameter http://tempuri.org/:aUpdatedObject.  
Die InnerException-Nachricht war "Das Element "http://tempuri.org/:aUpdatedObject"  
enthält Daten eines Typs, der dem Namen "http://schemas.datacontract.org/2004/07
/ServerApp:TransmissionClass" zugeordnet ist.   
Dem Deserialisierungsprogramm ist kein Typ bekannt, der diesem Namen zugeordnet ist.  
Verwenden Sie ggf. einen DataContractResolver, oder fügen Sie den entsprechenden Typ für "TransmissionClass" der Liste der bekannten Typen hinzu.  
Verwenden Sie dazu z. B. das Attribut "KnownTypeAttribute", oder fügen Sie den Typ der an DataContractSerializer übergebenen Liste von bekannten Typen hinzu.".  
Weitere Details finden Sie unter "InnerException".

Однако я применил атрибут KnownTypeAttribute к WCFреализация сервиса.

1 Ответ

3 голосов
/ 22 июня 2011

В общем, кто бы ни (сервер или клиент) десериализует параметр или возвращаемое значение, он должен знать, какие типы (точнее, какие контракты) ожидать во время выполнения, чтобы сделать это. В этом случае объявленный параметр типа object не дает клиенту достаточно информации для десериализации того, что сервер может отправлять обратно. Замена его типом , поддерживаемым DataContractSerializer (и украшенным [KnownType], если сервер планирует отправлять экземпляры подкласса в обратном вызове), решает эту проблему.

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

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

[ServiceContract]
interface ISearch
{
    [OperationContract]
    SearchResult Search(SearchQuery query);
}

[DataContract]
[KnownType(typeof(Subclass1InSharedAssembly)), etc...]
class SearchResult
{
    [DataMember]
    BaseClassDeclaredInSharedAssembly Value { get; set; }
}

Поскольку я хотел, чтобы сервер и клиент использовали (полезные) типы общих сборок, у меня была ссылка на общую сборку в обоих, и я решил не создавать для них прокси-типы ... и поэтому svcutil didn ' не генерировать для меня никаких KnownTypeAttribute. Частичные занятия спасли мой бекон; На клиенте вы можете сделать это:

// generated proxy .cs
[DataContract]
partial class SearchResult
{
    ...
}

// hand-written .cs
[KnownType(typeof(Subclass1InSharedAssembly)), etc.]
partial class SearchResult
{
    // Now the client knows how to deserialise derived types.
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...