实现 PropertyChangedBase 时的 caliburn.micro 序列化问题 [英] caliburn.micro serialization issue when implementing PropertyChangedBase

查看:18
本文介绍了实现 PropertyChangedBase 时的 caliburn.micro 序列化问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

公共类人{公共整数 ID {get;set;}公共字符串名字{get;set;}...}

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

问题:

为了实现 NotifyOfPropertyChanged(),我为Person"设置了一个父类PropertyChangedBase".

public class Person : PropertyChangedBase{公共整数 ID {get;set;}私人字符串_firstName;公共字符串名字{得到 { 返回 _firstName;}放{_firstName = 值;NotifyOfPropertyChange(() => FirstName);}}...}

但是这次Person"类的属性在接收端有NULL值.

我猜序列化/反序列化有问题.这仅在实施 PropertyChangedBase 时发生.

谁能帮我解决这个问题?

解决方案

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

[数据契约]公共类人员:PropertyChangedBase{[数据成员]公共 int Id { 获取;放;}私人字符串_firstName;[数据成员]公共字符串名字{获取;放;}}

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

命名空间 Caliburn.Micro {[数据合约]公共类 PropertyChangedBase : INotifyPropertyChangedEx{}}

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

[AttributeUsageAttribute(AttributeTargets.Class|AttributeTargets.Struct|AttributeTargets.Enum, Inherited = false,AllowMultiple = false)]公共密封类 DataContractAttribute : 属性

但是,HttpClientExtensions.PostAsJsonAsync 使用 JsonMediaTypeFormatter,其中默认使用 Json.NET 库来执行序列化. 而 Json.NET 不尊重 Inherited = false DataContractAttribute 的属性,如此处

所述<块引用>

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

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

所以你毕竟需要添加这些属性.

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

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

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

I'm developing a client/server data driven application using caliburn.micro for frontend and Asp.net WebApi 2 for backend.

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

The application contains a class called "Person". A "Person" object is serialized (JSON) and moved back and forth from client to server using simple REST protocal. The solution works fine without any problem.

Problem:

I have set a parent class "PropertyChangedBase" for "Person" in order to implement NotifyOfPropertyChanged().

public class Person : PropertyChangedBase
{
    public int Id {get;set;}

    private string _firstName;
    public string FirstName
    {
        get { return _firstName; }
        set
        {
            _firstName = value;
            NotifyOfPropertyChange(() => FirstName);
        }
    }
    ...
}

But this time the properties of class "Person" has NULL values at receiving end.

I guess there is a problem with serialization / deserialization. This is only happens when implementing PropertyChangedBase.

Can anyone help me to overcome this issue?

解决方案

You need to add the [DataContract] attribute to your Person class and the [DataMember] attribute to every property and field you wish to serialize:

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

    private string _firstName;

    [DataMember]
    public string FirstName { get; set; }
}

You need to do this because the caliburn.micro base class PropertyChangedBase has the [DataContract] attribute:

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

But why should this be necessary? In theory, the presence of the DataContractAttribute applied to the base class should not affect your derived Person class, because DataContractAttribute sets AttributeUsageAttribute.Inherited = false:

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

However, HttpClientExtensions.PostAsJsonAsync uses the default instance of JsonMediaTypeFormatter, which by default uses the Json.NET library to perform serialization. And Json.NET does not respect the Inherited = false attribute of DataContractAttribute, as is explained here

[Json.NET] detects the DataContractAttribute on the base class and assumes opt-in serialization.

(For confirmation see Question about inheritance behavior of DataContract #872 which confirms this behavior of Json.NET continues to be as intended.)

So you need to add those attributes after all.

Alternatively, if you do not want to have to apply data contract attributes all over your derived classes, you could switch to DataContractJsonSerializer following the instructions here: JSON and XML Serialization in ASP.NET Web API:

If you prefer, you can configure the JsonMediaTypeFormatter class to use the DataContractJsonSerializer instead of Json.NET. To do so, set the UseDataContractJsonSerializer property to true:

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

这篇关于实现 PropertyChangedBase 时的 caliburn.micro 序列化问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆