C# 为什么可以';t';非串行化';属性是否可以在类级别使用?如何防止类的序列化?

C# 为什么可以';t';非串行化';属性是否可以在类级别使用?如何防止类的序列化?,c#,binary-serialization,nonserializedattribute,C#,Binary Serialization,Nonserializedattribute,我有一个使用二进制序列化进行深度克隆的数据对象。此数据对象支持属性更改事件,例如PriceChanged 假设我在PriceChanged上附加了一个处理程序。当代码试图序列化PriceChanged时,它会抛出一个异常,即处理程序未标记为可序列化 我的选择: 在序列化之前,我无法轻松地从事件中删除所有处理程序 我不想将处理程序标记为可序列化的,因为我还必须递归地标记所有处理程序依赖项 我不想将PriceChanged标记为非序列化-像这样的事件可能有几十个处理程序。编辑:我不能这样做的另一个

我有一个使用二进制序列化进行深度克隆的数据对象。此数据对象支持属性更改事件,例如PriceChanged

假设我在PriceChanged上附加了一个处理程序。当代码试图序列化PriceChanged时,它会抛出一个异常,即处理程序未标记为可序列化

我的选择:

  • 在序列化之前,我无法轻松地从事件中删除所有处理程序
  • 我不想将处理程序标记为可序列化的,因为我还必须递归地标记所有处理程序依赖项
  • 我不想将PriceChanged标记为非序列化-像这样的事件可能有几十个处理程序。编辑:我不能这样做的另一个原因是,数据类(以及事件)是生成的,我不能直接控制生成代码。理想情况下,生成代码只会将所有事件标记为非序列化
  • 理想情况下,我希望.NET在这一点上停止遍历对象图,并将其设置为“叶子”那么为什么.NET不允许将整个类标记为非序列化类呢?
--

我最终解决了这个问题,使处理程序实现ISerializable,并且在serialize构造函数/GetDataObject方法中什么也不做。但是,处理程序仍然是序列化的,只是它的所有依赖项都设置为null——所以我也必须考虑到这一点


有没有更好的方法来防止整个类的序列化?也就是说,一种不需要考虑空依赖项的方法?

尽管我倾向于不同意这种方法(我会简单地将事件标记为非序列化,不管有多少)您可能可以使用序列化代理来实现这一点

其思想是创建一个实现ISerializationSubrogate的对象,并且基本上执行您已经在做的事情——在GetObjectData和SetObjectData方法中什么都不做。区别在于您将自定义委托的序列化,而不是包含它的类

比如:

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;
    }
}
然后,使用以下过程向格式化程序注册此文件。然后,每当格式化程序遇到委托时,它都使用代理,而不是直接序列化委托

…有几十个事件

就个人而言,我只需添加非序列化标记,对于类似字段的事件,最容易通过以下方式完成:

[field: NonSerialized]
public event SomeEventType SomeEventName;
(您不需要添加手动支持代理)

您的序列化要求到底是什么<代码>二进制格式化程序在许多方面是序列化程序中最不友好的;对事件的影响有点难看,如果存储,则非常脆弱(在我看来,它只适合传输,不适合存储)

但是,;有很多好的替代方案可以支持最常见的“深度克隆”方案:

  • XmlSerializer
    (但仅限于公共成员)
  • DataContractSerializer
    /
    NetDataContractSerializer
  • protobuf net(包括用于此目的的
    序列化程序.DeepClone

(请注意,大多数序列化支持都需要额外的属性,因此与首先添加
[NonSerialized]
属性没有太大区别!)

感谢您向我介绍序列化代理的概念。我喜欢它——至少我不必“污染”原始数据类。不过有一件事-我还没有尝试过,但我怀疑我仍然会有空依赖性问题?我不这么认为。由于您将拦截委托的序列化并有效地取消它,因此处理程序根本不会被序列化。要求是支持不断演变的数据对象的深度克隆,即从一个版本到另一个版本的新字段/属性。我已经在上面提到了为什么将字段标记为非序列化不是一个真正的选项。