如何在WCF中使用DataContract/DataMember序列化Func <int,int>(甚至是一般委托)类型字段

GDS*_*GDS 8 c# wcf serialization

我正在尝试序列化Func<int, int>标记有[DataMember]类的标记的字段[DataContract],其目标或Lambda表达式定义也是合同的一部分,或者甚至可以在类本身中.

我正在使用一个自定义DataContractResolver,当我取消标记该Func字段时,它非常有效,但是当我标记它时,它不能解析System.DelegateSerializationHolder序列化所需的类型.我试图将此类型添加到我的自定义,DataContractResolver但我无法在系统命名空间中找到它.

我可以在[OnDeserialized]每个使用这个类的客户端类的方法中重新定义它,但是每次我使用这个类时我都需要这样做,当然我想避免(客户端类也是其中的一部分DataContract).

此序列化暂时用于将应用程序的状态保存到磁盘,因此保存委托(甚至是我不感兴趣的事件)具有逻辑意义,因为它是对象图的所有部分.

那么如何Func<int, int>使用WCF对其进行序列化DataContract呢?

Lua*_*aan 5

问题在于,无法为此使用默认的WCF序列化程序-委托序列化仅适用于.NET。

解决方法是NetDataContractSerializer改用。就您而言,具有持久性上下文(或多个File上下文):

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;
}
Run Code Online (Sandbox Code Playgroud)

请注意,序列化程序将仅维护有关委托的信息 -如果您仅对委托使用编译时方法,那很好,但是对于动态编译的方法将不起作用。被警告。

避免使用匿名函数也是一个好主意-尽管它们起作用,但它们也可能在不同的内部版本之间进行更改,从而使您的持久状态变为无效,可能会带来灾难性的副作用。别忘了,委托是通过方法+类名(以及返回类型和参数...)进行序列化的-当名称更改时,持久化的委托将指向具有旧名称的新方法。即使使用非匿名方法,也要尝试确保您从未更改过可能一直保留为委托的方法-理想情况下,如有必要,使用原始方法签名提供向后兼容的行为。

如果您发现自己增加了对网络序列化的支持,则只需添加more即可StreamingContextStates