KnownType для всех производных типов абстрактного класса?

У нас есть абстрактный класс, который является основой для ряда различных запросов, которые мы отправляем через службу WCF. Это отвратительный отвратительный хак, когда каждый раз, когда мы добавляем новый запрос, мы должны помнить о добавлении атрибута [KnownType] к этому базовому классу.

Есть ли способ указать DataContractSerializer рассматривать ВСЕ производные этого абстрактного типа как KnownType?


person Joe    schedule 07.06.2011    source источник


Ответы (4)


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

  1. При запуске службы загрузите через отражение типы, которые вы хотите предоставить. Например. если все ваши открытые объекты WCF происходят из общей абстрактной базы (или более), загрузите все типы из сборки, в которой они должны быть расположены. Кэшируйте эти типы статически из соображений производительности.

  2. Создайте статический метод, который возвращает указанные кэшированные типы со следующей сигнатурой: public static IEnumerable<Type> GetKnownTypes(ICustomAttributeProvider provider)

  3. Пометьте интерфейс WCF следующим атрибутом [ServiceKnownType("GetKnownTypes", typeof(StaticClassThatCachesTypes))]

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

person Dan C.    schedule 07.06.2011
comment
Спасибо за это. На самом деле это не масштабируется, если существует несколько базовых типов для разных видов контрактов (должен быть статический помощник для каждой базы), но он устраняет человеческий фактор. :) - person Joe; 07.06.2011
comment
@Джо: не обязательно. Если у вас есть несколько базовых классов, ничто не мешает вам загрузить все их производные типы за один раз на шаге 1. GetKnownTypes должен возвращать список типов. Фактические ограничения заключаются в том, что вы должны знать все свои базовые классы (и адаптировать загрузчик типов при добавлении нового), и вы должны знать, где они расположены. - person Dan C.; 08.06.2011
comment
Принятие этого как достойный обходной путь. Было бы неплохо иметь что-то более интеллектуальное на уровне языка/компилятора... - person Joe; 21.06.2011

Другой вариант, помимо предложенного Дэном К., — переключиться на NetDataContractSerializer — он не требует объявления известных типов, поскольку он тесно связан с точной реализацией контракта, поэтому вам нужно будет совместно использовать сборку, содержащую типы, между клиентом и сервером — и вы определенно потеряете совместимость в этом сценарии. Об этом есть несколько сообщений (я видел этот часто появляется в результатах google/bing).

person carlosfigueira    schedule 07.06.2011
comment
Да, я надеялся избежать этой зависимости. Спасибо за предложение. - person Joe; 07.06.2011

Вот пример того, как это делается с помощью PostSharp. . Посмотрите в конец поста.

person Paul Fryer    schedule 11.03.2013

Это пример достижения этого с помощью IL Weaving с использованием Fody/Mono.Cecil.

По сути, это расширение Fody, которое внедряет KnownTypeAttributes во время сборки с использованием IL Weaving.

Во время конвейера сборки расширение находит все базовые классы, помеченные атрибутом KnowsDeriveTypes (часть расширения), и добавит атрибут KnownTypeAttribute ко всем классам, производным (не обязательно напрямую) от одного из вышеперечисленных классов. базовые классы (с атрибутом KnowsDeriveTyepsAttribute).

Это еще один зеркало для сообщения и здесь вы можете найти репозиторий Github для расширения.

person m1o2    schedule 26.02.2018
comment
Не публикуйте ответы, содержащие только ссылки; если ссылка исчезнет, ​​то это бесполезный пост. - person Joe; 26.02.2018
comment
@Joe Я добавил краткое объяснение с большим количеством зеркал для ссылки. Я не уверен, что будет хорошей идеей объяснить весь пост в блоге в одном ответе Stackoverflow. - person m1o2; 27.02.2018