以下课程是一个人为的例子。我希望最简单的方法是每次将'isVisible'字段序列化为'true'时,无论它被设置为什么。
在实际代码中......这是一个更大的对象,并且有一些不同的构造函数可以从不同的点调用。
现在,我可以想到两种方式。
创建一个'OnSerializing()'方法,该方法使用反射在序列化期间将属性设置为“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”。
答案 0 :(得分:1)
您希望在反序列化期间将字段private readonly bool isVisible;
初始化为true
。不幸的是,DataContractSerializer
doesn't call any constructor of your class所以没有明显的,简单的方法来做到这一点。
您提出的解决方案 - 在序列化期间始终发出<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
,因为它是supported by the data contract serializer,并在流式构造函数中初始化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;
}
}
然而,这是不推荐,因为您现在需要手动序列化所有班级的成员。