我正在尝试序列化一个Func< int,int>标有[DataMember]的字段,标有[DataContract]的类,其目标或Lambda表达式定义也是合同的一部分,或者甚至可以在类本身中.
我正在使用自定义DataContractResolver,当我取消标记Func字段时,它非常有效,但是当我标记它时,它不解析序列化所需的System.DelegateSerializationHolder类型.我试图将此类型添加到我的自定义DataContractResolver,但我无法在系统命名空间中找到它.
我可以在每个使用这个类的客户端类的[OnDeserialized]方法中重新定义它,但是每次我使用这个类时我都需要这样做,当然我想避免(客户端类也是DataContract的一部分) ).
此序列化暂时用于将应用程序的状态保存到磁盘,因此保存委托(甚至是我不感兴趣的事件)具有逻辑意义,因为它是对象图的所有部分.
那么如何序列化这个Func< int,int>使用WCF的DataContract?
解决方法
问题在于,无法使用默认的WCF序列化程序 – 委托序列化只能用于.NET.
解决方案是使用NetDataContractSerializer.在您的情况下,使用持久性上下文(或文件上下文):
var context = new StreamingContext(StreamingContextStates.Persistence); var s = new System.Runtime.Serialization.NetDataContractSerializer(); var sb = new StringBuilder(); using (var writer = new XmlTextWriter(new StringWriter(sb))) { s.WriteObject(writer,new Test() { SomeFunc = (int i) => "Hi".Dump().Length }); } sb.ToString().Dump(); [DataContract] class Test { [DataMember] public Func<int,int> SomeFunc; }
请注意,序列化程序只会维护有关委托的信息 – 如果您只为代理使用编译时方法,这很好,但它不适用于动态编译的方法.被警告.
避免匿名函数也是一个好主意 – 虽然它们可以工作,但它们也可能在不同的构建之间发生变化,导致持久状态变为无效,可能带来灾难性的副作用.不要忘记,委托由方法类名称(和返回类型,以及参数…)序列化 – 当名称更改时,持久委托将指向具有旧名称的新方法.即使使用非匿名方法,也要确保永远不要更改可能作为委托持久保存的方法 – 理想情况下,如果需要,使用原始方法签名提供向后兼容的行为.