在。NET中可以将字段标记为不可序列化,在序列化过程中会被跳过。
我正在寻找一种简单的方法,该方法允许我在运行时控制是否应序列化特定字段。
您指的是“将字段标记为不可序列化”,因此我假设您正在使用BinaryFormatter
and [NonSerialized]
。如果是这样,进行条件序列化的唯一方法是实现ISerializable
和添加类似的构造函数,并将逻辑放入GetObjectData
实现中。不过,这很乏味且容易出错。我建议查看 protobuf-net,它具有更简单的条件序列化,使用TypeDescriptor
and使用的标准模式XmlSerializer
,但仍然是二进制输出(BinaryFormatter
实际上比 更有效)。具体来说:
[ProtoContract]
public class SomeType {
[ProtoMember(1)]
public string Name {get;set;}
private bool ShouldSerializeName() {
// return true to serialize Name, false otherwise
}
}
这ShouldSerialize*
是一个标准的基于名称的约定——没有特定于这个序列化程序。
这是相同的 via 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);
}
}