C# 数据协定和序列化只读布尔字段始终'true'



下面的类是一个精心设计的例子。我想要每次序列化"isVisible"字段时将其序列化为"true"的最简单方法。。。不管它被设置为什么。

在真实的代码中。。。这是一个大得多的对象,有几个不同的构造函数,它们从不同的点调用。

现在,我可以想出两种方法。

  1. 创建一个"OnSerialization()"方法,该方法在序列化期间使用反射将属性设置为"true"。(我实际上不确定这是否可行……但看起来会的)。

  2. 在启动类序列化的方法中。。。在序列化之前,创建isVisible为true的所有新项。

    [DataContract]
    public class MapItem
    {
    public MapItem(bool isVisible)
    {
    this.isVisible = isVisible;
    }
    [DataMember]
    private readonly bool isVisible;
    public bool IsVisible => isVisible;
    }
    

为什么我需要这个?基本上,我需要加载这些项目,并使它们在加载后始终可见。运行应用程序时。。。MapItems可能变得可见/不可见。因此,我希望XML始终具有<isVisible>true</isVisible>,或者我希望MapItem中的值仅在反序列化时为"true"。

您希望在反序列化期间将字段private readonly bool isVisible;初始化为true。不幸的是,DataContractSerializer不调用类的任何构造函数,因此没有明显的、简单的方法来实现这一点。

您提出的解决方案——在序列化期间始终发出<isVisible>true</isVisible>,并利用数据协定序列化程序反序列化只读字段值的能力——并不理想,因为精心编制的XML文件(例如<isVisible>false甚至缺失的文件)可能会在应用程序中引入意外行为。

相反,考虑以下不需要序列化isVisible:值的替代方案

  1. 修改只读字段的名称和语义,使默认值为正确的所需值。在这种情况下,您需要将当前的isVisible替换为private readonly bool isNotVisible;:

    [DataContract]
    public class MapItem
    {
    // Do not mark with [DataContract] as deserialized instances should always have the default value
    private readonly bool isNotVisible; 
    public MapItem(bool isVisible)
    {
    this.isNotVisible = !isVisible;
    }
    public bool IsVisible { get { return !isNotVisible; } }
    }
    
  2. 使用反射设置[OnDeserializing]回调中的字段值:

    [DataContract]
    public class MapItem
    {
    public MapItem(bool isVisible)
    {
    this.isVisible = isVisible;
    }
    // Do not mark with [DataContract] as deserialized instances should always have the value
    // set in the OnDeserializing() callback.
    private readonly bool isVisible;
    public bool IsVisible { get { return isVisible; } }
    [OnDeserializing]
    void OnDeserializing(StreamingContext context)
    {
    typeof(MapItem)
    .GetField(nameof(isVisible), BindingFlags.Instance | BindingFlags.NonPublic)
    .SetValue(this, true);
    }
    }
    
  3. 最后,您可以实现ISerializable,因为它受到数据契约序列化程序的支持,并在流式构造函数中将isVisible初始化为true

    [Serializable]
    public class MapItem : ISerializable
    {
    public MapItem(bool isVisible)
    {
    this.isVisible = isVisible;
    }
    private readonly bool isVisible;
    public bool IsVisible { get { return isVisible; } }
    #region ISerializable Members
    public virtual void GetObjectData(SerializationInfo info, StreamingContext context)
    {
    }
    #endregion
    protected MapItem(SerializationInfo info, StreamingContext context)
    {
    this.isVisible = true;
    }
    }
    

    但是,这是不推荐的,因为您现在需要手动序列化类的所有成员。

相关内容

  • 没有找到相关文章

最新更新