Передача экземпляра анонимного типа по WCF

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

На стороне клиента я создаю анонимный текстовый объект

var obj = new {FirstName="John", LastName="Doe"}

и передайте его методу. Я получаю исключение:

Type '<>f__AnonymousType0`2[System.String,System.String]' cannot be serialized. 
Consider marking it with the DataContractAttribute attribute, and marking all 
of its members you want serialized with the DataMemberAttribute attribute.  
See the Microsoft .NET Framework documentation for other supported types.

Я не могу отметить тип или его участников с атрибутами сериализации, потому что нет действительно никакого типа, ни свойств, объявленных явно. Существует ли способ преодолеть ту проблему?

20
задан casperOne 22 February 2010 в 02:16
поделиться

5 ответов

Не делайте этого.

Это попытка быть умным. Не надо. Просто объявите нужный тип данных и используйте его. Если вам нужен более расплывчатый тип данных, просто используйте какое-то сопоставление "ключ-значение".

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

17
ответ дан 29 November 2019 в 23:40
поделиться

Ответы предполагающие, что вы не можете использовать анонимный тип через WCF, неверны.

Если вы используете стандартный DataContractSerializer для сериализации ваших типов на канале, то да, ответы верны. Это связано с тем, что DataContractSerializer поддерживает следующие сценарии:

  1. Типы, сериализованные с помощью атрибута Serializable
  2. Типы, сериализованные с помощью XML Serialization
  3. Типы, сериализованные с помощью атрибута DataContract
  4. Plain-Old-C#-Object (POCO) Serialization

Соответственно, они не работают с анонимными типами из-за следующего:

  1. Вы не можете применять атрибуты к анонимным типам.
  2. Сериализация XML требует конструктора без параметров по умолчанию, которого у анонимных типов нет.
  3. То же, что и 1.
  4. То же, что и 2.

Однако, вы не вынуждены использовать DataContractSerializer для сериализации ваших сообщений в WCF. Вы можете создать пользовательский форматтер сообщений, который вы можете использовать для выполнения сериализации самостоятельно.

У вас есть проблема, если типы, которые вы отправляете в качестве результатов запросов, являются анонимными типами. Когда вы получите результаты обратно, они будут иметь определенное имя в пространстве имен (не в смысле .NET, а в смысле SOA), и вам придется обрабатывать отображение этого конкретного типа обратно в анонимный тип. Однако, поскольку у вас нет доступа к фактическому анонимному типу или способам его построения в коде (по крайней мере, динамическим способом), у вас нет выбора, кроме как передать его как объект, если он будет передан вам обратно, что делает его в некотором роде бесполезным, поскольку всем придется использовать плохую практику, такую как dynamic (сама по себе не плохая практика, но чтобы обойти эти ограничения в данном случае, да), или cast-by-example.

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

19
ответ дан 29 November 2019 в 23:40
поделиться

Нет, нет. Хотя существуют приемы и приемы для возврата объектов анонимного типа из метода, вы не можете отправлять их через WCF.

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

2
ответ дан 29 November 2019 в 23:40
поделиться

Вы уже получили ответ. Этого нельзя сделать.

На самом деле, вы не можете передавать экземпляр анонимного типа из одного метода в другой в пределах вашей программы. Вы определенно не можете передавать их между программами.

1
ответ дан 29 November 2019 в 23:40
поделиться

Как было сказано ранее, объекты должны быть десериализуемыми, поэтому вам придется заранее определить структуру. Однако вы можете использовать наследование для их определения и, следовательно, уменьшить боль. WCF предоставляет атрибут KnownType, позволяющий операции службы получать объект базового класса и десериализовать его в объект производного класса. Таким образом, у вас по-прежнему будет только одна (или несколько) сервисных операций, которые могут обрабатывать все ваши сценарии.

0
ответ дан 29 November 2019 в 23:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: