C#反序列化派生并具有引用的对象

我有一个类型节点的对象。 Node.cs

我打电话时序列化工作如下:

var nodeSer = JsonConvert.SerializeObject(mynode, Formatting.Indented, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects }); 

我的问题是以下调用不起作用。

 var n = JsonConvert.DeserializeObject(nodeSer, new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, TypeNameHandling = TypeNameHandling.Auto }); 

该调用导致以下错误:

 Newtonsoft.Json.JsonSerializationException: "ISerializable type 'System.Action' does not have a valid constructor. To correctly implement ISerializable a constructor that takes SerializationInfo and StreamingContext parameters should be present. Path 'Size.ValueChanged', line 35, position 5." 

我如何设计反序列化调用?

Json.NET不会序列化事件,因此HousePlan存储库的PropertyChangedBase基类型中的public event PropertyChangedEventHandler PropertyChanged不应在(反)序列化期间导致问题。

但是,该存储库中至少有一种类型具有System.Action委托,而不是在值更改时要处理的事件,特别是BindablePoint

 public class BindablePoint: PropertyChangedBase { public double X { get { return Value.X; } set { Value = new Point(value, Value.Y); } } public double Y { get { return Value.Y; } set { Value = new Point( Value.X, value); } } private Point _value; public Point Value { get { return _value; } set { _value = value; OnPropertyChanged("Value"); OnPropertyChanged("X"); OnPropertyChanged("Y"); if (ValueChanged != null) ValueChanged(); } } // This property is causing problems for Json.NET public Action ValueChanged; } 

目前尚不清楚为什么代理而不是事件被用于此目的,但是Json.NET无法对System.Action进行反序列化。 实际上,序列化和反序列化这些委托是没有意义的,因为它们是在Node的构造函数中分配的:

 public class Node: DiagramObject { public Node() { Size.ValueChanged = RecalculateSnaps; Location.ValueChanged = RecalculateSnaps; } 

一个简单的解决方案是使用[JsonIgnore]标记这些属性

  [JsonIgnore] public Action ValueChanged; 

第二个简单的解决方案是用适当的事件替换委托,Json.NET现在将忽略它:

  public event EventHandler ValueChanged; 

如果由于某种原因您无法更改这些类型,则可以创建自动忽略所有委托类型属性的自定义ContractResolver

 public class IgnorePropertiesOfTypeContractResolver : IgnorePropertiesOfTypeContractResolver { // As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons. // http://www.newtonsoft.com/json/help/html/ContractResolver.htm // http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm // "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance." static IgnorePropertiesOfTypeContractResolver instance; static IgnorePropertiesOfTypeContractResolver() { instance = new IgnorePropertiesOfTypeContractResolver(); } public static IgnorePropertiesOfTypeContractResolver Instance { get { return instance; } } public IgnorePropertiesOfTypeContractResolver() : base(new[] { typeof(T) }) { } } ///  /// Contract resolver to ignore properties of any number of given types. ///  public class IgnorePropertiesOfTypeContractResolver : DefaultContractResolver { readonly HashSet toIgnore; public IgnorePropertiesOfTypeContractResolver(IEnumerable toIgnore) { if (toIgnore == null) throw new ArgumentNullException(); this.toIgnore = new HashSet(toIgnore); } protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) { var property = base.CreateProperty(member, memberSerialization); if (property.PropertyType.BaseTypesAndSelf().Any(t => toIgnore.Contains(t))) { property.Ignored = true; } return property; } } public static class TypeExtensions { public static IEnumerable BaseTypesAndSelf(this Type type) { while (type != null) { yield return type; type = type.BaseType; } } } 

现在使用以下设置进行序列化:

 var settings = new JsonSerializerSettings { PreserveReferencesHandling = PreserveReferencesHandling.Objects, ContractResolver = IgnorePropertiesOfTypeContractResolver.Instance, }; 

ValueChanged属性将不再序列化或反序列化。