简体   繁体   中英

Conditionally serialize/deserialize attribute

I have a class whose objects must serialize/deserialize an attribute depending on a bool value

[System.SerializableAttribute()]
public class Foo
{
    private string myField;
    private bool myFieldSerializes;

    //Parameterless construction for serializing purposes
    public Foo() { }

    public Foo(string myField, bool myFieldSerializes)
    {
        this.myField = myField;
        this.myFieldSerializes = myFieldSerializes;
    }

    public string MyField
    {
        get {return this.myField;}
        set {this.myField = value;}
    }

    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool MyFieldSerializes
    {
        get {return this.myFieldSerialzes;}
        set {this.myFieldSerialzes = value;}
    }
}

This is how it should work:

  • If i create an instance and set myFieldSerializes to 'true', when serializing the object (with XMLSerialize), myField must be serialized (included on the XML message). If is set to 'false', it should be ignored.

  • When deserializing (with XMLDeserialize), the boolean myFieldSerializes should tell me if myField has been deserialized (in other words, it was present in the XML file).

What is the way to implement this behavior?

Thanks! :)

Your requirements match the propertyNameSpecified pattern of XmlSerializer . From the docs :

If a schema includes an element that is optional ... [one] option is to use a special pattern to create a Boolean field recognized by the XmlSerializer, and to apply the XmlIgnoreAttribute to the field. The pattern is created in the form of propertyNameSpecified . For example, if there is a field named "MyFirstName" you would also create a field named "MyFirstNameSpecified" that instructs the XmlSerializer whether to generate the XML element named "MyFirstName".

What's convenient about this pattern is that, beyond the documented behavior, during deserialization, XmlSerializer will set the propertyNameSpecified to true if the property was encountered -- which is exactly what you need. Thus your class should look like:

public class Foo
{
    private string myField;
    private bool myFieldSerializes;

    //Parameterless construction for serializing purposes
    public Foo() { }

    public Foo(string myField, bool myFieldSerializes)
    {
        this.myField = myField;
        this.myFieldSerializes = myFieldSerializes;
    }

    [XmlElement(IsNullable = true)] // Emit a value even when null as long as MyFieldSpecified == true
    public string MyField
    {
        get { return this.myField; }
        set { this.myField = value; }
    }

    [System.Xml.Serialization.XmlIgnoreAttribute()]
    public bool MyFieldSpecified { get { return myFieldSerializes; } set { myFieldSerializes = value; } }
}

(Adding [XmlElement(IsNullable = true)] to your MyField property ensures that an element will always be emitted when MyFieldSpecified == true , even if the field itself is null .)

Prototype fiddle .

Seems you can use ShouldSerialize approach:

https://msdn.microsoft.com/en-us/library/53b8022e(v=vs.110).aspx

public bool ShouldSerializeMyField() 
{
      return this.myFieldSerializes;
}

You could implement the ISerializable interface which allows you to specify what you want to serialize and deserialize.

Therefore you would need to implement an GetObjectData method like:

public void GetObjectData(SerializationInfo info, StreamingContext context)
{
    // Use the AddValue method to specify serialized values.
    info.AddValue("props", myProperty_value, typeof(string));

}

and a Constructor which takes SerializationInfo and StreamingContext as parameters like

// The special constructor is used to deserialize values.
public Foo(SerializationInfo info, StreamingContext context)
{
    // Reset the property value using the GetValue method.
    myProperty_value = (string) info.GetValue("props", typeof(string));
}

In this way you can decide during serialization and deserialization what to do (eg set the value of a propert or not, ...)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM