В общем, кто бы ни (сервер или клиент) десериализует параметр или возвращаемое значение, он должен знать, какие типы (точнее, какие контракты) ожидать во время выполнения, чтобы сделать это. В этом случае объявленный параметр типа 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.
}