Hiding properties for the C# XmlSerializer through partial classes

自闭症网瘾萝莉.ら 提交于 2019-12-11 06:19:09

问题


According to W3C the XSD boolean datatype is defined as 0, 1, true or false. An external party has provided an xsd I have no influence over and as you might have guessed the boolean values they require are not the default values that the C# XmlSerializer serializes booleans into. True and false are not accepted, only 0 and 1. What makes the case even worse, the classes that are serialized into xml are auto generated by xsd.exe and as such I do not want to alter these classes because developers that come after me will most likely forget this extra step after running the xsd.exe tool.

For this reason the following solution is problematic:

[XmlIgnore]
public bool MyValue { get; set; }

/// <summary>Get a value purely for serialization purposes</summary>
[XmlElement("MyValue")]
public string MyValueSerialize
{
    get { return this.MyValue ? "1" : "0"; }
    set { this.MyValue = XmlConvert.ToBoolean(value); }
}

Also from what I have understood, there is a future possibility some booleans have to be serialized into 0 or 1 while others into true or false (i know..). Until that situation arises implementing my custom XmlSerializer (see: XML Serialize boolean as 0 and 1) is probably an acceptable solution but before that I hope someone has a few tips on the following interesting possibility:

Assume xsd.exe has generated the following code:

namespace MyUnitTests.Classes {
    [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "urn:XX:YYYY:01")]
    [System.Xml.Serialization.XmlRootAttribute(Namespace = "urn:XX:01", IsNullable = false)]     
    public partial class MyRootClass {
        public MyBoolClass MyBoolClass { get; set; }
    }

    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "XX:ZZ:01")]
    public partial class MyBoolClass {
        [System.Xml.Serialization.XmlElementAttribute("Node")]
        public bool Item { get; set; }
    }
}

So the idea is that MyBoolClass is a partial class for which I can provide my own custom implementation in a separate definition where I take care of the true -> 1 false -> 0 problem.

My code for this is as follows:

namespace MyUnitTests.Classes {
    public interface IMyBoolClass {
        [XmlIgnore]
        bool Item { get; set; }
    }

    public partial class MyBoolClass : IMyBoolClass {
        [XmlElement("Node")]
        public string SerializableItem {
            get { return this.Item ? "1" : "0"; }
            set { this.Item = System.Xml.XmlConvert.ToBoolean(value); }
        }
    }
}

So I have an interface IMyBoolClass that I designed to take care of the XmlIgnore and declared the property SerializableItem that should serialize the actual 0 and 1. Unfortunately the exception that occurs indicates that XmlIgnore is not applied to the MyBoolClass.Item that is generated by xsd.exe.

I have the following UnitTest

[TestMethod]
public void TestMethod2() {
    MyRootClass root = new MyRootClass() {
        MyBoolClass = new MyBoolClass() {
            Item = false
        }
    };

    XmlSerializer xmlSerializer = new XmlSerializer(typeof(MyRootClass));

    using (StringWriter writer = new StringWriter()) {
        xmlSerializer.Serialize(writer, root);
        string xml = writer.ToString();
    }
}

the following exceptions occur:

There was an error reflecting property 'MyBoolClass
There was an error reflecting property 'Item'
The XML element 'Node' from namespace 'XX:ZZ:01' is already present in the current scope. Use XML attributes to specify another XML name or namespace for the element

Obviously changing:

[XmlElement("Node")]

In my own partial definition of MyBoolClass Into:

[XmlElement("Node1")] 

Solves the problem and results in the following XML:

<?xml version="1.0" encoding="utf-16"?>
<MyRootClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="urn:XX:01">
  <MyBoolClass xmlns="urn:XX:YYYY:01">
    <Node1 xmlns="XX:ZZ:01">0</Node1>
    <Node xmlns="XX:ZZ:01">false</Node>
  </MyBoolClass>
</MyRootClass>

So the question how to "hide" the:

public bool Item { get; set; }

In the class MyBoolClass that is generated by xsd.exe for the XmlSerializer?

Any tips and tricks will be greatly appreciated, also if anybody has some other brilliant ideas I would be really very grateful.

来源:https://stackoverflow.com/questions/36722407/hiding-properties-for-the-c-sharp-xmlserializer-through-partial-classes

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!