WCF 和 .NET 5.0:字节数组反序列化问题
WCF and .NET 5.0: Issue with byte array deserialization
我正在尝试使用现有的 WCF 服务(基本绑定),但我遇到了一些与接收到的消息的反序列化相关的问题。让我先展示消息的片段:
<s:Body>
<ObtemUtilizadoresResponse xmlns="http://xxx. pt/Mercados"><ObtemUtilizadoresResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<util>
<Id>123</Id>
<ver>AAAAAACL5j4=</ver>
<im>-2</im>
<n>User 123</n>
</util>
....
</s:Body>
最初,我首先创建一个新的 DTO 来执行反序列化,如下所示:
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
[field: DataMember(Name = "Id")]
public int Id { get; set; }
[field: DataMember(Name = "ver")]
private byte[] Version { get; set; }
[field: DataMember(Name = "n")]
public string Nome { get; set; }
[field: DataMember(Name = "im")]
public int IdMercado { get; set; }
}
即使创建了实例,它也只会填充 Id
和 Version
属性。如果我删除 Version
属性,那么剩余的属性将被填充。为了填充所有属性,我不得不将 Version
移动到基数 class:
[DataContract(Namespace = "http://xxx. pt/Mercados", Name = "vb")]
public class Base {
[field: DataMember(Name = "ver")]
private byte[] Version { get; set; }
}
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador:Base {
... //removed Version property
有人知道为什么会这样吗?
谢谢。
经过一番挖掘,似乎可以解释这种行为。当您使用 DataContractSerializer
时,类型内的默认序列化顺序是按字母顺序排列的,如果您使用的是 class 层次结构,则顺序是自上而下。如果序列化顺序不匹配,成员将被初始化为其默认值。这就是为什么当我引入基数 class 时一切正常的原因(因为服务使用基数 class 作为被序列化的类型)。
因此,如果您想在客户端扁平化层次结构,则需要求助于 DataMemberAttribute
的 Order
属性。您可以对每个 属性 应用正确的顺序位置(以便它模仿服务器上正在序列化的内容),或者您可以通过为属于层次结构的每个级别的属性赋予相同的值来“分组”它们(并且依赖于具有相同顺序值的属性的默认字母顺序 - 顺便说一下,如果您还设置它,则它基于 Name
属性):
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
[field: DataMember(Name = "Id", Order = 1)]
public int Id { get; set; }
[field: DataMember(Name = "ver", Order = 1)]
private byte[] Version { get; set; }
[field: DataMember(Name = "n", Order = 2)]
public string Nome { get; set; }
[field: DataMember(Name = "im", Order = 2)]
public int IdMercado { get; set; }
}
我正在尝试使用现有的 WCF 服务(基本绑定),但我遇到了一些与接收到的消息的反序列化相关的问题。让我先展示消息的片段:
<s:Body>
<ObtemUtilizadoresResponse xmlns="http://xxx. pt/Mercados"><ObtemUtilizadoresResult xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<util>
<Id>123</Id>
<ver>AAAAAACL5j4=</ver>
<im>-2</im>
<n>User 123</n>
</util>
....
</s:Body>
最初,我首先创建一个新的 DTO 来执行反序列化,如下所示:
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
[field: DataMember(Name = "Id")]
public int Id { get; set; }
[field: DataMember(Name = "ver")]
private byte[] Version { get; set; }
[field: DataMember(Name = "n")]
public string Nome { get; set; }
[field: DataMember(Name = "im")]
public int IdMercado { get; set; }
}
即使创建了实例,它也只会填充 Id
和 Version
属性。如果我删除 Version
属性,那么剩余的属性将被填充。为了填充所有属性,我不得不将 Version
移动到基数 class:
[DataContract(Namespace = "http://xxx. pt/Mercados", Name = "vb")]
public class Base {
[field: DataMember(Name = "ver")]
private byte[] Version { get; set; }
}
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador:Base {
... //removed Version property
有人知道为什么会这样吗?
谢谢。
经过一番挖掘,似乎可以解释这种行为。当您使用 DataContractSerializer
时,类型内的默认序列化顺序是按字母顺序排列的,如果您使用的是 class 层次结构,则顺序是自上而下。如果序列化顺序不匹配,成员将被初始化为其默认值。这就是为什么当我引入基数 class 时一切正常的原因(因为服务使用基数 class 作为被序列化的类型)。
因此,如果您想在客户端扁平化层次结构,则需要求助于 DataMemberAttribute
的 Order
属性。您可以对每个 属性 应用正确的顺序位置(以便它模仿服务器上正在序列化的内容),或者您可以通过为属于层次结构的每个级别的属性赋予相同的值来“分组”它们(并且依赖于具有相同顺序值的属性的默认字母顺序 - 顺便说一下,如果您还设置它,则它基于 Name
属性):
[DataContract(Namespace = "http://xxx.pt/Mercados", Name = "util")]
public class Utilizador {
[field: DataMember(Name = "Id", Order = 1)]
public int Id { get; set; }
[field: DataMember(Name = "ver", Order = 1)]
private byte[] Version { get; set; }
[field: DataMember(Name = "n", Order = 2)]
public string Nome { get; set; }
[field: DataMember(Name = "im", Order = 2)]
public int IdMercado { get; set; }
}