下面的类是一个精心设计的例子。我想要每次序列化"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始终具有<isVisible>true</isVisible>
,或者我希望MapItem中的值仅在反序列化时为"true"。
您希望在反序列化期间将字段private readonly bool isVisible;
初始化为true
。不幸的是,DataContractSerializer
不调用类的任何构造函数,因此没有明显的、简单的方法来实现这一点。
您提出的解决方案——在序列化期间始终发出<isVisible>true</isVisible>
,并利用数据协定序列化程序反序列化只读字段值的能力——并不理想,因为精心编制的XML文件(例如<isVisible>
是false
甚至缺失的文件)可能会在应用程序中引入意外行为。
相反,考虑以下不需要序列化isVisible
:值的替代方案
-
修改只读字段的名称和语义,使默认值为正确的所需值。在这种情况下,您需要将当前的
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; } } }
-
使用反射设置
[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); } }
-
最后,您可以实现
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; } }
但是,这是不推荐的,因为您现在需要手动序列化类的所有成员。