Подтвердить что ты не робот

Передача экземпляра анонимного типа по 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.

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

4b9b3361

Ответ 1

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

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

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

Ответ 2

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

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

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

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

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

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

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

Ответ 3

Вы можете сериализовать объект в строку JSON и отправить его через WCF, например:

//in WCF Server
dynamic mysentclass = new { FirstName = "John", LastName = "Doe" };
string jsonstring = JsonConvert.SerializeObject(mysentclass, Newtonsoft.Json.Formatting.Indented);
//send the string through WCF

//in WCF client
dynamic myreceivedclass = JsonConvert.DeserializeObject<dynamic>(jsonstring);
MessageBox.Show(myreceivedclass.FirstName.ToString() + " " + myreceivedclass.LastName.ToString());

В примере используется Json.Net, который можно получить здесь:

http://www.nuget.org/packages/Newtonsoft.Json/

Вы также можете использовать System.Web.Script.Serialization.JavaScriptSerializer(в System.Web.Extensions.dll), который не такой мощный, как Json.Net, но будет достаточным для простых объектов.

Ответ 4

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

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

Ответ 5

У вас уже есть ответ. Это невозможно сделать.

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

Ответ 6

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