C# C DataContract和序列化只读布尔字段始终为“true”

C# C DataContract和序列化只读布尔字段始终为“true”,c#,serialization,datacontractserializer,C#,Serialization,Datacontractserializer,下面的类是一个人为的例子。我想用最简单的方法在每次序列化“isVisible”字段时将其序列化为“true”…不管它设置为什么 在实际代码中…这是一个更大的对象,并且有几个不同的构造函数,这些构造函数是从不同的点调用的 现在,我可以想出两种方法 创建一个“onserialization”方法,该方法在序列化期间使用反射将属性设置为“true”。我不确定这会不会奏效,但看起来会的 在启动类序列化的方法中…在序列化之前,创建isVisible为“true”的所有新项 [DataContract] p

下面的类是一个人为的例子。我想用最简单的方法在每次序列化“isVisible”字段时将其序列化为“true”…不管它设置为什么

在实际代码中…这是一个更大的对象,并且有几个不同的构造函数,这些构造函数是从不同的点调用的

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

创建一个“onserialization”方法,该方法在序列化期间使用反射将属性设置为“true”。我不确定这会不会奏效,但看起来会的

在启动类序列化的方法中…在序列化之前,创建isVisible为“true”的所有新项

[DataContract]
public class MapItem
{
    public MapItem(bool isVisible)
    {
        this.isVisible = isVisible;
    }

    [DataMember]
    private readonly bool isVisible;

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

您希望字段private readonly bool可见;在反序列化期间初始化为true。不幸的是,没有明显的、简单的方法来做到这一点

您提出的解决方案—在序列化过程中始终发出true,并利用数据协定序列化程序反序列化只读字段值的能力—不太理想,因为一个制作糟糕的XML文件(例如,其中的XML文件为false或甚至缺失)可能会在应用程序中引入意外行为

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

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

使用反射设置回调中的字段值:

[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);
    }
}
最后,您可以按原样实现,并在流式构造函数中将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;
    }
}
但是,不建议这样做,因为现在需要手动序列化类的所有成员


我想用最简单的方法在每次序列化“isVisible”字段时将其序列化为“true”-您的意思是希望true出现在序列化的XML中,还是希望在序列化过程中将MapItem类中的实际字段值修改为true?如果您始终希望它为true,为什么选择它为false?你真的需要序列化它吗?您可以将其默认为true并忽略IgnoreDataMemberAttribute中的IsVisible吗?@dbc是的,我希望XML始终为true,或者我希望只有在反序列化时MapItem中的值才为true。基本上,我需要加载这些项目,并使它们在加载后始终可见。运行应用程序时…MapItems可能会变为可见/不可见。@TyCobb如上所述。运行应用程序时,这些项目可能可见或不可见。只有在加载时,我才需要将它们全部设置为可见。但是,我认为省时的方法是将它们保存为可见,而不是以这种方式加载它们。这里的基本问题是,您无法方便地将只读bool字段初始化为true。您愿意将字段的含义从isVisible转换为isNotVisible吗?在这种情况下,默认值将是正确的值。
[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;
    }
}