【问题标题】:WCF - Serialize/Deserialize boolean values as yes/no instead of true/false?WCF - 将布尔值序列化/反序列化为是/否而不是真/假?
【发布时间】:2019-01-05 01:27:05
【问题描述】:

我正在编写一个 WCF Web 服务,它对 XML 文档进行序列化和反序列化。 XML 文件用作 ERP 和我的 .Net Web 服务之间的通信机制。我面临的问题是我无法控制 ERP 的输出,它发送的是/否作为逻辑值,需要在我的服务中反序列化为 bool 变量。

我正在使用带有 DataContract 和 DataMember 装饰的 DataContractSerializer。

DataContractSerializer ser = new DataContractSerializer(typeof(Order));
Order GenerateOrder = (Order)ser.ReadObject(readDoc.CreateReader());

如何将 yes/no 反序列化为 bool 属性?

【问题讨论】:

  • 相关:Can .NET convert “Yes” & “No” to boolean without If? 这对您意味着,当您呈现或呈现值时,应该对布尔值进行是/否转换 - IOW 您在 UI 层中转换它而不是试图在数据层深处的某个地方做这件事。
  • 我认为问题是“为什么”?数据转换应该在中间处理,通常是一个 ETL 层

标签: c# wcf datacontractserializer


【解决方案1】:

Boolean 是一种原生 .NET 类型,.NET 使用 XML Schemas 中定义的原生 xsd:boolean 对其进行序列化。所以不,您不能将布尔值序列化/反序列化为是/否。

另一种解决方案,您可以定义自定义枚举并使用 EnumMember 标签自定义其序列化行为。

[DataContract]
public enum MyBoolean
{
    [EnumMember(Value = "No")]
    False,

    [EnumMember(Value = "Yes")]
    True
}

如果你使用 Yes, No 作为枚举值,你甚至可以这样写:

[DataContract]
public enum MyBoolean
{
    [EnumMember]
    No,

    [EnumMember]
    Yes
}

【讨论】:

    【解决方案2】:

    在大多数情况下使用 DataContract(s) 就足够了,但在互操作性场景中需要自定义序列化。虽然 .NET 不使用“是”和“否”作为布尔值,但其他平台/语言可能会这样做。因此,您必须利用 WCF 中的其他序列化方法。

    考虑实现数据协定的 IXmlSerializable 接口,该接口允许您在低级别控制序列化和反序列化。

    考虑这个在 WCF 服务中使用的 POCO 示例:

       public class Animal : IXmlSerializable
    {
    
        public Animal()
        {
    
        }
    
        bool _isBipedal;
        public bool IsBipedal
        {
            get { return _isBipedal; }
            set { _isBipedal = value; }
        }
    
        string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    
        public XmlSchema GetSchema()
        {
            return null;
        }
    
        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();
    
            Name = reader.GetAttribute("Name");
            reader.ReadStartElement(); 
    
            IsBipedal = bool.Parse(reader.ReadElementString("IsBipedal") == "Yes" ? "true" : "false");
            reader.ReadEndElement(); 
        }
    
        public void WriteXml(XmlWriter writer)
        {
            writer.WriteAttributeString("Name", Name);
            writer.WriteElementString("IsBipedal", IsBipedal ? "Yes" : "No");
        }
    
    }
    

    请注意,此类不使用 [DataContract] 属性,而是实现 IXmlSerializable。针对 WCF 操作运行客户端后 返回这个Animal类型的列表,我们得到以下序列化的内容(注意我们这里的wire/response可以使用“Yes”作为布尔值用Fiddler检查:

    <s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetAnimalsResponse xmlns="http://tempuri.org/"><GetAnimalsResult xmlns:a="http://schemas.datacontract.org/2004/07/CustomWcfSerialization.Common" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
    


    否是

    关于 IXmlSerializable - 请注意,ReadXml 方法将负责反序列化对象,而 WriteXml 方法将负责序列化对象。 GetSchema 方法在大多数情况下可以返回 null。

    我准备了一个带有 Visual Studio 解决方案的小型演示项目,展示了如何在此处完成此操作:

    git clone git@bitbucket.org:toreaurstad/wcfixmlserializabledemo.git

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      • 2020-05-20
      • 2016-03-21
      • 1970-01-01
      • 2011-04-06
      • 2016-09-11
      相关资源
      最近更新 更多