实现PropertyChangedBase时的caliburn.micro序列化问题

我正在开发一个客户端/服务器数据驱动的应用程序,使用caliburn.micro作为前端,使用Asp.net WebApi 2作为后端。

public class Person { public int Id {get;set;} public string FirstName{get;set;} ... } 

该应用程序包含一个名为“Person”的类。 “Person”对象是序列化的(JSON),并使用简单的REST协议从客户端到服务器来回移动。 解决方案正常运行没有任何问题。

问题:

我为“Person”设置了一个父类“PropertyChangedBase”,以实现NotifyOfPropertyChanged()。

 public class Person : PropertyChangedBase { public int Id {get;set;} private string _firstName; public string FirstName { get { return _firstName; } set { _firstName = value; NotifyOfPropertyChange(() => FirstName); } } ... } 

但这次类“Person”的属性在接收端具有NULL值。

我猜序列化/反序列化存在问题。 这仅在实现PropertyChangedBase时发生。

任何人都可以帮我解决这个问题吗?

您需要将[DataContract]属性添加到Person类,并将[DataMember]属性添加到要序列化的每个属性和字段:

 [DataContract] public class Person : PropertyChangedBase { [DataMember] public int Id { get; set; } private string _firstName; [DataMember] public string FirstName { get; set; } } 

您需要这样做,因为caliburn.micro基类PropertyChangedBase具有[DataContract]属性:

 namespace Caliburn.Micro { [DataContract] public class PropertyChangedBase : INotifyPropertyChangedEx { } } 

但为什么这有必要呢? 理论上,应用于基类的DataContractAttribute的存在不应该影响派生的Person类,因为DataContractAttribute设置AttributeUsageAttribute.Inherited = false

 [AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Enum, Inherited = false, AllowMultiple = false)] public sealed class DataContractAttribute : Attribute 

但是, HttpClientExtensions.PostAsJsonAsync使用JsonMediaTypeFormatter的默认实例,默认情况下使用Json.NET库执行序列化。 并且Json.NET不尊重DataContractAttributeInherited = false属性,如此处所述

[Json.NET]检测基类上的DataContractAttribute并假定选择加入序列化。

(有关确认,请参阅有关DataContract#872的inheritance行为的问题,该问题确认Json.NET的这种行为仍然符合预期。)

所以你需要添加这些属性。

或者,如果您不希望在派生类中应用数据协定属性,则可以按照此处的说明切换到DataContractJsonSerializer : ASP.NET Web API中的JSON和XML序列化 :

如果您愿意,可以将JsonMediaTypeFormatter类配置为使用DataContractJsonSerializer而不是Json.NET。 为此,请将UseDataContractJsonSerializer属性设置为true

 var json = GlobalConfiguration.Configuration.Formatters.JsonFormatter; json.UseDataContractJsonSerializer = true;