【问题标题】:Ignore a property during serialization using BinaryFormatter only if its null在序列化期间使用 BinaryFormatter 忽略一个属性,仅当它为 null
【发布时间】:2020-04-10 20:40:25
【问题描述】:

我目前正在使用BinaryFormatter 创建流。我知道如果我希望在序列化期间被 BinaryFormatter 忽略,我可以使用属性 [field: NonSerialized] 标记属性。我的问题是是否有办法让我指定在二进制序列化期间应忽略字段的所有空属性?我目前正在做这样的事情来获取流

       var formatter = new BinaryFormatter();
        using (var stream = new MemoryStream())
        {
            formatter.Serialize(stream, MyObjectinstance);
        }

【问题讨论】:

标签: c# serialization binary-serialization


【解决方案1】:

并非专门为此目的而设计,但ISerializationSurrogate 可以提供帮助。

稍后我将编辑并丰富我的答案,但以下内容可以满足您的需求,但无法为嵌套对象实现相同的效果。

这里的 obj 参数是你的类的实例。如果它的值为空,我们只需省略向序列化信息添加一个字段:

public class NullFieldOmittingSurrogate : ISerializationSurrogate
{
    void ISerializationSurrogate.GetObjectData(object obj, SerializationInfo info, StreamingContext context)
    {
        if (obj != null)
        {
            foreach (FieldInfo field in obj.GetType().GetFields
                (BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance))
            {
                object fieldValue = field.GetValue(obj);
                if (fieldValue != null)
                {
                    info.AddValue(field.Name, fieldValue);
                }
            }
        }
    }

    object ISerializationSurrogate.SetObjectData(object obj, SerializationInfo info, StreamingContext context, ISurrogateSelector selector)
    {
        // The deserialization works without the need for this surrogate
        throw new NotImplementedException();
    }
}

我们需要将这个代理传递给我们的二进制格式化程序,所以这里有一个方法可以将这个和其他必需的信息传递给它:

public static void SerializeObject(object myObjectInstance, Stream destinationStream)
{
    SurrogateSelector surrogateSelector = new SurrogateSelector();
    surrogateSelector.AddSurrogate
    (
        myObjectInstance.GetType(),
        new StreamingContext(StreamingContextStates.All),
        new NullFieldOmittingSurrogate()
    );
    IFormatter serializer = new BinaryFormatter();
    serializer.SurrogateSelector = surrogateSelector;
    serializer.Serialize(destinationStream, myObjectInstance);
}

最后,如何使用:(SerClass 是无关紧要的,它是一个有 4 个属性的类,所有类型均为 object,用于单元测试)

public static void Main()
{
    MemoryStream memoryStream = new MemoryStream();
    SerializeObject
    (
        new SerClass()
        {
            Prop2 = 5,
            Prop4 = "ABCD",
            Nested = new SerClassNested() { Prop1 = 8, Prop3 = "EFGH" }
        },
        memoryStream
    );

    SerClass serClass = new BinaryFormatter().Deserialize(memoryStream) as SerClass;
}

希望这会有所帮助。我仍在处理嵌套类类型字段。

【讨论】:

    【解决方案2】:

    您将其从序列化中排除的特定用例是什么? Null 几乎不会占用任何空间,这不会提高反序列化或序列化性能。在反序列化时,您也可以通过处理 OnDeserialized 事件以不同方式处理 null。

    【讨论】:

    • 这不是哈希的问题。我正在计算该流的哈希值。空值会改变哈希
    猜你喜欢
    • 1970-01-01
    • 2016-02-03
    • 2013-08-17
    • 1970-01-01
    • 2016-05-26
    • 2012-12-09
    • 1970-01-01
    • 2014-06-13
    相关资源
    最近更新 更多