通过WCF传递匿名类型的实例

时间:2010-02-21 19:35:19

标签: wcf anonymous-types datacontractserializer datacontract

我有一个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.

我无法使用序列化属性标记类型或其成员,因为实际上没有明确声明的类型或属性。有没有办法克服这个问题?

6 个答案:

答案 0 :(得分:19)

answers suggesting错误的can't use an anonymous type over WCF

如果您使用默认的DataContractSerializer来序列化频道上的类型,那么答案是正确的。这是因为DataContractSerializer支持以下方案:

  1. 使用Serializable attribute
  2. 序列化的类型
  3. 使用XML Serialization
  4. 序列化的类型
  5. 使用DataContract attribute
  6. 序列化的类型
  7. Plain-Old-C#-Object (POCO) Serialization
  8. 由于以下原因,它们分别因匿名类型而失败:

    1. 您无法将属性应用于匿名类型。
    2. XML Serialization需要一个默认的无参数构造函数,匿名类型没有。
    3. 与1相同。
    4. 与2相同。
    5. ,您不必使用DataContractSerializer在WCF中序列化您的邮件。您可以创建一个custom message formatter,您可以使用它来自行执行序列化。

      如果您作为请求结果发送的类型是匿名类型,则会出现问题。当你得到结果时,它将在命名空间中具有明确的名称(不是在.NET意义上,而是在SOA意义上),并且您将不得不将该具体类型的映射处理回匿名类型。但是,因为您无法访问实际的匿名类型或在代码中构造它的方法(至少以动态方式),所以除了将它作为对象传递给它之外别无选择,如果它被传递给您,使它变得毫无价值,因为每个人都必须使用不良的做法,例如动态(本身不是一种不好的做法,但在这种情况下解决这些限制,是的),或cast-by-example

      所以最后我会说,虽然它确实可能序列化匿名类型并通过网络发送它们,但是调用的工作通常是不值得的。

答案 1 :(得分:17)

不要这样做。

这是一种聪明的尝试。别。只需声明您需要的数据类型,然后使用它。如果需要更松散定义的数据类型,只需使用某种键值映射。

你需要花5分钟时间写一些可以解决这个问题的东西。使用这样的任何技术都会花费你几个小时的调试时间。

答案 2 :(得分:4)

您可以将对象序列化为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强大,但对于简单对象就足够了。

答案 3 :(得分:2)

不,没有。虽然有一些技巧和技术可以从方法返回匿名类型的对象,但您无法通过WCF发送它们。

WCF需要知道将要发送的所有具体类型,因为您实际上并不只是调用.NET方法。相反,消息调用将转换为序列化消息,因此,通过WCF调用传递的任何“事物”必须可序列化 - 没有例外。

答案 4 :(得分:1)

你已经得到了答案。它无法完成。

实际上,您无法将一个匿名类型的实例从一个方法传递到程序中的另一个。你肯定无法在程序之间传递

答案 5 :(得分:0)

如前所述,对象必须是可反序列化的,因此您必须事先定义结构。但是,您可以使用继承来定义它们,从而降低痛苦。 WCF提供KnownType属性以允许服务操作接收基类的对象并将其反序列化为派生类的对象。因此,您仍然只能拥有一个(或几个)可以处理所有方案的服务操作。