22

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

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

4

6 回答 6

20

建议您不能在 WCF 上使用匿名类型答案是错误的。

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

  1. 使用属性序列化的类型Serializable
  2. 使用XML 序列化序列化的类型
  3. 使用属性序列化的类型DataContract
  4. Plain-Old-C#-Object (POCO) 序列化

由于以下原因,它们分别因匿名类型而失败:

  1. 您不能将属性应用于匿名类型。
  2. XML 序列化需要一个默认的无参数构造函数,而匿名类型则没有。
  3. 同 1。
  4. 同2。

但是,您不必DataContractSerializer在 WCF 中使用 序列化消息。您可以创建一个自定义消息格式化程序,您可以使用它自己执行序列化。

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

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

于 2010-02-21T20:27:02.627 回答
19

不要这样做。

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

你需要 5 分钟来写一些可以永久处理这个问题的东西。使用像这样的任何技术都会在未来的某个时间点花费您数小时的调试时间。

于 2010-02-28T05:06:36.207 回答
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 强大,但对于简单的对象就足够了。

于 2013-10-18T13:02:51.813 回答
2

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

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

于 2010-02-21T19:38:15.363 回答
1

你已经得到了答案。这是不可能的。

事实上,您不能程序中将匿名类型的实例从一种方法传递到另一种方法。你当然不能在程序之间传递它们。

于 2010-02-21T19:37:14.443 回答
0

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

于 2010-02-28T05:03:32.830 回答