在。您可以将字段标记为不可序列化,并且在序列化期间将跳过该字段。
我正在寻找一种简单的方法,它允许我在运行时控制是否应该序列化特定字段。
答案 0 :(得分:3)
您指的是“将字段标记为不可序列化”,因此我假设您使用的是BinaryFormatter
和[NonSerialized]
。如果是这样,执行条件序列化的唯一方法是实现ISerializable
并添加类似的构造函数,并将逻辑放在GetObjectData
实现中。但这很乏味且容易出错。我建议使用TypeDescriptor
和XmlSerializer
使用的标准模式来查看具有更简单条件序列化的protobuf-net,但仍然是二进制输出(实际上比BinaryFormatter
更高效) 。具体做法是:
[ProtoContract]
public class SomeType {
[ProtoMember(1)]
public string Name {get;set;}
private bool ShouldSerializeName() {
// return true to serialize Name, false otherwise
}
}
这个ShouldSerialize*
是一个基于标准名称的约定 - 没有特定于此序列化程序。
以下是ISerializable
:
[Serializable]
public class SomeType : ISerializable
{
public SomeType() { }
public string Name { get; set; }
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
if (/* should serialize Name */) info.AddValue("Name", Name);
//... all other fields
}
protected SomeType(SerializationInfo info, StreamingContext context)
{
foreach (SerializationEntry entry in info)
{
switch (entry.Name)
{
case "Name": Name = (string)entry.Value; break;
//... all other fields
}
}
}
}
维护更多;特别是,在使用ISerializable
时,您必须对所有成员负责 - 但是,如果您只使用protobuf-net,则可以根据具体情况处理每个成员。
实际上,你也可以混合搭配,即如果你仍然坚持使用BinaryFormatter
,你仍然可以将工作卸载到protobuf-net,但是它会改变格式(因此与旧数据不兼容)。例如:
[Serializable, ProtoContract]
public class SomeType : ISerializable
{
public SomeType() { }
[ProtoMember(1)]
public string Name { get; set; }
private bool ShouldSerializeName() { /* condition */ }
void ISerializable.GetObjectData(
SerializationInfo info, StreamingContext context)
{
Serializer.Serialize(info, this);
}
protected SomeType(SerializationInfo info, StreamingContext context)
{
Serializer.Merge(info, this);
}
}