Понимание ServiceKnownType в WCF

У меня есть небольшая проблема с пониманием ServiceKnownType в WCF.

Взятый из этот блог, следующий код не работает:

[DataContract(Namespace = "http://mycompany.com/")]
public class Shape{…}

[DataContract(Namespace = "http://mycompany.com/")]
public class Circle : Shape {…}

[ServiceContract]
public interface IMyServer
{
    [OperationContract]
    bool AddShape(Shape shape);
}

.

IMyServer client = new ChannelFactory<IMyServer>(binding, endPoint).CreateChannel();

client.AddShape(new Circle());

Причина, по которой он не работает, заключается в том, что вы пытаетесь добавить круг, но servicecontract допускает только Shape. Вы должны что-то делать с известными типами, но я немного смущен тем, как это работает.

Поскольку этот код находится в сервисе, почему он не знает автоматически, что Circle получен из Shape? Кроме того, что действительно делает ServiceKnownType?

Когда ServiceKnownType помещается под DataContract, очевидно, что он работает. Я предполагаю, что он говорит, что этот тип объекта, называемый Shape, также может быть кругом. У меня возникли проблемы с пониманием того, почему это будет сделано так, потому что если вы добавите новый тип типа Square, вам придется добавить к классу Shape класс ServiceKnownType. Разве это не имело бы смысла, если бы он не мог этого сделать, чтобы положить KnownType на квадрат, а не в форму? Итак, Квадрат говорит, что я - Форма, и вам не нужно возиться с классом Shape? Если ваш класс Shape встроен в библиотеку, и вы хотите создать свою собственную тупиковую форму, такую ​​как DiamondShape, вы не можете добавить ее в класс Shape, потому что у вас нет доступа к исходному коду.

Ответ 1

Проблема в том, что WCF не входит во все сборки и пытается найти все возможные подтипы Shape. Он также не передает информацию о типе (сборка, полное имя типа) с XML-документом.

Итак, хотя было бы не проблемой генерировать тег "Circle" в исходящем XML, входящий десериализатор не знал бы, что с этим делать.

"Хак" KnownType похож на реестр известных типов, который должен быть реализован обеими сторонами. Это явное. В этом реестре десериализатор знает, что "Круг" десериализует тип X без каких-либо проблем и без необходимости анализировать все доступные или доступные сборки для производных типов.

Помните, что Square не говорит "Я форма", это как тег XML, и из этого вам нелегко и автоматически знать, какой .NET-класс использовать.