简体   繁体   English

为什么不能在类级别使用'NonSerialized'属性?如何防止类的序列化?

[英]Why can't the 'NonSerialized' attribute be used at the class level? How to prevent serialization of a class?

I have a data object that is deep-cloned using a binary serialization. 我有一个使用二进制序列化进行深度克隆的数据对象。 This data object supports property changed events, for example, PriceChanged. 此数据对象支持属性更改事件,例如PriceChanged。

Let's say I attached a handler to PriceChanged. 假设我将处理程序附加到PriceChanged。 When the code attempts to serialize PriceChanged, it throws an exception that the handler isn't marked as serializable. 当代码尝试序列化PriceChanged时,它会抛出一个异常,即处理程序未标记为可序列化。

My alternatives: 我的选择:

  • I can't easily remove all handlers from the event before serialization 在序列化之前,我无法轻松地从事件中删除所有处理程序
  • I don't want to mark the handler as serializable because I'd have to recursively mark all the handlers dependencies as well. 我不想将处理程序标记为可序列化,因为我还必须递归地标记所有处理程序依赖项。
  • I don't want to mark PriceChanged as NonSerialized - there are tens of events like this that could potentially have handlers. 我不想将PriceChanged标记为NonSerialized - 有这样的数十个事件可能有处理程序。 EDIT: Another reason why I can't do this is because the data classes (and hence the events) are generated and I don't have direct control over the generation code. 编辑:我不能这样做的另一个原因是因为生成了数据类(以及事件),并且我无法直接控制生成代码。 Ideally, the generation code would just mark all events as NonSerialized. 理想情况下,生成代码只会将所有事件标记为NonSerialized。
  • Ideally, I'd like .NET to just stop going down the object graph at that point and make that a 'leaf'. 理想情况下,我希望.NET能够在此时停止对象图并使其成为“叶子”。 So why doesn't .NET allow an entire class to be marked as NonSerialized? 那么为什么.NET不允许将整个类标记为NonSerialized?

-- -

I finally worked around this problem by making the handler implement ISerializable and doing nothing in the serialize constructor/ GetDataObject method. 我终于通过使处理程序实现ISerializable并在serialize构造函数/ GetDataObject方法中不执行任何操作来解决此问题。 But, the handler still is serialized, just with all its dependencies set to null - so I had to account for that as well. 但是,处理程序仍然是序列化的,只是将其所有依赖项设置为null - 所以我也必须考虑到这一点。

Is there a better way to prevent serialization of an entire class? 有没有更好的方法来阻止整个类的序列化? That is, one that doesn't require accounting for the null dependencies? 也就是说,不需要考虑空依赖关系?

While I tend to disagree with the approach (I would simply mark the events as NonSerialized, regardless of how many there are) you could probably do this using serialization surrogates. 虽然我倾向于不同意这种方法(我只是将事件标记为NonSerialized,无论有多少)你可以使用序列化代理来做到这一点。

The idea is that you create an object that implements ISerializationSurrogate and basically does what you're already doing - nothing in the GetObjectData and SetObjectData methods. 我们的想法是,您创建一个实现ISerializationSurrogate的对象,并基本上执行您正在执行的操作 - GetObjectData和SetObjectData方法中没有任何内容。 The difference is that you would be customizing the serialization of the delegate, not the class containing it. 不同之处在于您将自定义委托的序列化,而不是包含它的类。

Something like: 就像是:

class DelegateSerializationSurrogate : ISerializationSurrogate {
    public void GetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
    }
    public object SetObjectData(object obj, SerializationInfo info, StreamingContext context) {
        // do nothing
        return null;
    }
}

Then you register this with the formatter using the procedures outlined in this MSDN column . 然后使用本MSDN专栏中列出的步骤将其注册到格式化程序。 Then whenever the formatter encounters a delegate, it uses the surrogate instead of serializating the delegate directly. 然后,只要格式化程序遇到委托,它就会使用代理而不是直接对委托进行序列化。

...there are tens of events... ......有几十个事件......

Personally, then I'd just add the non-serialized markers, which for field-like events is most easily done via: 就个人而言,我只是添加非序列化标记,通过以下方式最容易完成类似字段事件:

[field: NonSerialized]
public event SomeEventType SomeEventName;

(you don't need to add a manual backing delegate) (您不需要添加手动支持委托)

What are your serialization requirements exactly? 您的序列化要求到底是什么? BinaryFormatter is in many ways the least friendly of the serializers; BinaryFormatter在许多方面是最不友好的序列化器; the implications on events are a bit ugly, and it is very brittle if stored (IMO it is only really suitable for transport, not for storage). 对事件的影响有点难看,如果存储它会非常脆弱(IMO它只适合运输而不是存储)。

However; 然而; there are plenty of good alternatives that would support most common "deep clone" scenarios: 有很多很好的选择可以支持最常见的“深度克隆”场景:

  • XmlSerializer (but limited to public members) XmlSerializer (但仅限于公共成员)
  • DataContractSerializer / NetDataContractSerializer DataContractSerializer / NetDataContractSerializer
  • protobuf-net (which includes Serializer.DeepClone for this purpose) protobuf-net(包括用于此目的的Serializer.DeepClone

(note that in most of those serialization support would require extra attributes, so not much different to adding the [NonSerialized] attributes in the first place!) (请注意,在大多数序列化支持中,需要额外的属性,因此首先添加[NonSerialized]属性并没有多大区别!)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM