wcf将枚举反序列化为字符串。
wcf将枚举反序列化为字符串。
我正在尝试使用WCF消费一个RESTful的web服务。由于我无法控制web服务的格式,所以我必须在这里做一些变通。然而,我似乎无法解决的一个主要问题是如何让WCF将枚举反序列化为字符串。
这是我的代码(名称已更改,显然):
[DataContract]
public enum Foo
{
[EnumMember( Value = "bar" )]
Bar,
[EnumMember( Value = "baz" )]
Baz
}
[DataContract]
public class UNameIt
{
[DataMember( Name = "id" )]
public long Id { get; private set; }
[DataMember( Name = "name" )]
public string Name { get; private set; }
[DataMember( Name = "foo" )]
public Foo Foo { get; private set; }
}
这是返回的无法反序列化的数据:
{
"id":123456,
"name":"John Doe",
"foo":"bar"
}
最后,抛出的异常:
出现错误,无法将类型为Service.Foo的对象进行反序列化。值“bar”无法解析为类型“Int64”。
我不想切换到使用XmlSerializer,因为除了其他很多缺点之外,它不允许我在属性上使用私有的setter。
我该如何让WCF(或者说DataContractSerializer)将我的枚举视为字符串值?
编辑:似乎无法做到这一点,并且这种行为是设计的方式。感谢微软,没有给我们选择的机会,不得不诉诸于一些技巧。按照somori的建议来做似乎是使用JSON和WCF获取字符串枚举的唯一方法。
问题的原因是在使用WCF客户端时,服务器使用了字符串枚举,而WCF客户端默认将枚举类型序列化为整数。解决方法是在WCF客户端中将枚举类型反序列化为字符串。
根据上述对话内容,可以看出问题的原因是WCF客户端默认将枚举类型序列化为整数,而服务器使用的是字符串枚举。由于WCF客户端无法更改服务器端的代码,因此需要在客户端进行处理。
解决方法可以参考以下链接:http://msdn.microsoft.com/en-us/library/aa347875.aspx。根据这篇文章中的内容,使用数据合同模型时,数据合同通常包含枚举成员的名称,而不是数值。然而,当使用数据合同模型时,如果接收方是WCF客户端,则导出的模式会保留数值。因此,可以通过在WCF客户端中映射枚举类型的数值与服务器端的字符串进行转换来解决问题。
具体的解决方法可以通过在WCF客户端中的数据合同中添加一个属性来实现。例如,假设服务器端的枚举类型为"Status",包含"Active"和"Inactive"两个成员。在WCF客户端中,可以定义一个数据合同,并在该合同中添加一个属性来将枚举类型的数值转换为相应的字符串:
[DataContract] public class DataContractExample { [DataMember] public EnumExample Status { get; set; } [DataMember] public string StatusString { get { return Status.ToString(); } set { Status = (EnumExample)Enum.Parse(typeof(EnumExample), value); } } }
通过将枚举类型的数值转换为字符串,并在数据合同中添加一个额外的属性来接收和发送枚举类型的字符串表示,可以解决WCF客户端与服务器端使用不同类型枚举的问题。
总结起来,问题的原因是WCF客户端将枚举类型序列化为整数,而服务器端使用字符串枚举。解决方法是在WCF客户端中将枚举类型反序列化为字符串,并通过在数据合同中添加一个额外的属性来实现枚举类型的转换。这样就能够在WCF客户端与服务器端之间正确地传递枚举类型的数据。
WCF将枚举反序列化为字符串的问题可能出现的原因是,当反序列化Json字符串时,可能会出现类型转换错误。这可能是由于Json字符串中的枚举值与服务器端定义的枚举类型不匹配造成的。解决此问题的一种方法是在将Json字符串发送到服务器之前对其进行URL编码。
下面是一个解决此问题的示例代码:
HttpUtility.UrlEncode(JSONInstruction) /*记得对字符串进行编码*/
通过使用HttpUtility.UrlEncode方法对Json字符串进行URL编码,可以确保特殊字符被正确处理,并且不会干扰枚举类型的反序列化过程。这样,服务器端就能正确地将Json字符串反序列化为枚举类型的字符串值。
问题:为什么在WCF中反序列化枚举时会以字符串形式出现,以及如何解决这个问题?
在WCF中,当我们使用DataContractSerializer对数据进行序列化和反序列化时,枚举类型默认会以整数形式进行序列化和反序列化。然而,有时候我们希望将枚举类型以字符串形式进行处理。例如,在某些情况下,我们希望将枚举类型的值作为JSON或XML中的一个字符串进行表示。
下面是一个示例代码片段,展示了在WCF中如何将枚举类型以字符串形式进行反序列化:
[DataContract] public class ExampleClass { [DataMember(Name = "foo")] private string foo { get; private set; } public Foo Foo { get { return Foo.Parse(foo); } } }
上述代码中,我们通过在DataMember属性中设置Name属性,将类中的私有字符串属性foo与枚举类型Foo进行关联。然后,我们在公共属性Foo中将字符串foo解析为枚举类型。
这种方法虽然有效,但却被认为是一种“hack”,并且并不是最佳实践。因此,我们希望找到一种更优雅的解决方案。
然而,根据Stack Overflow上的讨论(stackoverflow.com/questions/794838/794962#794962),实际上这种方法似乎是唯一可行的方式。这意味着,目前没有更好的解决方案来直接将枚举类型以字符串形式进行反序列化。
另外,有人可能会问,为什么我们不在Foo属性中添加一个setter方法。实际上,在这个特定的用例中,并不需要添加setter方法。反序列化器只会写入foo属性,而我们只需要读取Foo值,而不是设置它。
尽管在WCF中将枚举类型以字符串形式进行反序列化可能不太直接,但我们可以通过在类中添加一个私有字符串属性并在公共属性中解析它来实现这个目标。虽然这种方法被认为是一种“hack”,但目前似乎是唯一可行的方式。希望将来会出现更好的解决方案来处理这个问题。