您指的是“将字段标记为不可序列化”,因此我假设您使用的是BinaryFormatter 和[NonSerialized]。如果是这样,进行条件序列化的唯一方法是实现ISerializable 并添加类似的构造函数,并将逻辑放入GetObjectData 实现中。不过,这很乏味且容易出错。我建议查看 protobuf-net,它具有更简单的条件序列化,使用 TypeDescriptor 和 XmlSerializer 使用的标准模式,但仍然是二进制输出(实际上比 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);
}
}