【问题标题】:Conditionally serialize/deserialize attribute有条件地序列化/反序列化属性
【发布时间】:2016-03-23 04:49:36
【问题描述】:

我有一个类,其对象必须根据布尔值序列化/反序列化属性

[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;}
    }
}

它应该是这样工作的:

  • 如果我创建一个实例并将 myFieldSerializes 设置为“true”,则在序列化对象时(使用 XMLSerialize),myField 必须被序列化(包含在 XML 消息中)。如果设置为“false”,则应忽略。

  • 反序列化时(使用 XMLDeserialize),布尔值 myFieldSerializes 应该告诉我 myField 是否已反序列化(换句话说,它存在于 XML 文件中)。

实现这种行为的方法是什么?

谢谢! :)

【问题讨论】:

标签: c# xml serialization


【解决方案1】:

您的要求符合XmlSerializerpropertyNameSpecified 模式。来自docs

如果架构包含一个可选元素... [one] 选项是使用特殊模式创建 XmlSerializer 识别的布尔字段,并将 XmlIgnoreAttribute 应用于该字段。该模式以 propertyNameSpecified 的形式创建。例如,如果有一个名为“MyFirstName”的字段,您还将创建一个名为“MyFirstNameSpecified”的字段,它指示 XmlSerializer 是否生成名为“MyFirstName”的 XML 元素。

这种模式的方便之处在于,除了记录的行为之外,在反序列化期间,XmlSerializer 将在遇到属性时将 propertyNameSpecified 设置为 true ——这正是您所需要的。因此,您的课程应如下所示:

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; } }
}

(将[XmlElement(IsNullable = true)] 添加到您的MyField 属性可确保在MyFieldSpecified == true 时始终发出元素,即使该字段本身是null。)

原型fiddle.

【讨论】:

  • 谢谢!事实上,这正是我所处的情况:XSD 文件中的一个可选属性,xsd.exe 工具将其转换为“propertyName”和布尔“propertyNameSpecified”。我以为我必须手动控制序列化,但我看到序列化器可以正常工作:)
  • 这也适用于反序列化吗?当我想选择性地反序列化 XML 中的属性值时?
【解决方案2】:

您可以实现ISerializable 接口,该接口允许您指定要序列化和反序列化的内容。

因此,您需要实现 GetObjectData 方法,例如:

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

}

还有一个构造函数,它接受SerializationInfoStreamingContext 作为参数,例如

// 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));
}

通过这种方式,您可以决定在序列化和反序列化期间做什么(例如,设置属性的值与否,...)

【讨论】:

    【解决方案3】:

    看来你可以使用 ShouldSerialize 方法:

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

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

    【讨论】:

    猜你喜欢
    • 2016-04-06
    • 2021-05-26
    • 2022-01-17
    • 1970-01-01
    • 2012-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-22
    相关资源
    最近更新 更多