.net序列化:如何有选择地忽略数据字段

时间:2012-08-09 09:46:33

标签: .net binary-serialization

在。您可以将字段标记为不可序列化,并且在序列化期间将跳过该字段。

我正在寻找一种简单的方法,它允许我在运行时控制是否应该序列化特定字段。

1 个答案:

答案 0 :(得分:3)

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