9

今天是个好日子,

我是一名独立游戏开发者,过去主要与 XNA 合作,而在另一个极端,我主要与商业工具集合作。然而,XNA 的范围非常有限,我正在构建一个跨平台抽象层来针对多个平台。

长话短说,我需要比 [Serializable] 更广泛地访问的 xml 序列化,并且有人指出我需要数据契约。我一直在做很多研究,但找不到任何关于系统基础知识的好信息,与继承和覆盖有关。

我的问题的关键是...

[DataContract]
public class Node
{
    private string name;

    public string Name { get { return name; } set { name = value; } }
    public virtual float Rotation { get { return 0f; } set { } }
}

[DataContract]
public class FancyNode : Node
{
    private float rotation;

    public override float Rotation { get { return rotation; } set { rotation = value; } }
}

如果我序列化一个'FancyNode','Rotation'会被正确序列化,'Name'会被序列化吗?

追问: 本来想早点问的,当时想不起来。序列化程序处理程序如何覆盖 [IgnoreDataMember] 属性?例如...

[DataContract]
public class Simple
{
    [IgnoreDataMember]
    public virtual string Value { get { return ""; } set { } }
}

[DataContract]
public class Complex : Simple
{
    private string value;

    public override string Value { get { return value; } set { this.value = value; } }
}

“复杂”中的“价值”会被序列化吗?一些答案表明,如果不使用 [DataMember] 标记,则所有属性都将被序列化。如果是这样,基类的 [IgnoreDataMember] 属性是否有任何影响?

4

4 回答 4

6

据我所知,DataContract 是一种“选择加入”的序列化方法,即除非你装饰它(告诉序列化程序你想序列化它),否则它不会序列化

因此,对于上面的示例,您需要将 [DataMember] 添加到要序列化的属性中

使用标准的 Serializable 属性,序列化程序会查看所有字段并仅忽略您标记为 NonSerialized 的字段

这里有一些例子:

http://jamescbender.azurewebsites.net/?p=651

查看注释部分以获取有关序列化内容的信息以及所发生情况的粗略概述:

http://msdn.microsoft.com/en-us/library/ms733127.aspx

编辑:我也看不出任何曾经标记为 [DataMember] 的字段无法正确序列化的任何原因。序列化的 DataContract 方法还可以处理循环引用——其他序列化有时会遇到问题:

http://msdn.microsoft.com/en-us/library/hh241056.aspx

于 2012-06-20T08:47:31.773 回答
6

一些答案中提出的一些想法不清楚。请让我把它们清理干净。首先,使用 DataContract 的序列化器可用于序列化未使用 DataContract 修饰的类型。您只需要通知 serailizer 即可。

例如,DataContractJsonSerializer 类会将一个类型序列化为一个 JSON 对象(通常是一个字符串)。您只需要告诉它您正在序列化的对象的类型,然后是它可能引用的任何其他类型:

var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(MyClass), new Type[] { Type1, Type2, Type3 });

序列化器将自动序列化该类型的每个公共字段和属性。有关详细信息,请参阅http://msdn.microsoft.com/en-us/ms733127

DataContractAttribute 标记类型

使用 标记类型后DataContractAttribute,您将该类型转换为自动已知的类型(您不需要将其作为子类型提供),然后将其转换为属性,并将字段转换为选择加入模式。

因此,您必须使用DataMemberAttribute. 这意味着IgnoreDataMemberAttribute是无用的。是的,序列化程序不会查找它,因为任何未标记的DataMemberAttribute内容都会被自动忽略。

未标记的 DataContractAttribute 类型

在序列化未应用 DataContractAttribute 的类型时,如前所述,每个公共属性或字段都将被序列化。因此,IgnoreDataMemberAttribute这里使用 来防止属性或字段被序列化。

于 2013-12-05T05:16:29.020 回答
1

您应该[DataMember]在应由合同公开的属性中包含该属性。

[DataContract]
public class FancyNode : Node
{
    private float rotation;

    [DataMember]
    public override float Rotation { get { return rotation; } set { rotation = value; } }
}

请注意,Windows Communication Foundation (WCF) 使用 Data Contract Serializer 来序列化和反序列化数据(将其转换为 XML 或从 XML 转换)。所以实际上你仍在使用 Xml 序列化。

于 2012-06-20T08:46:53.333 回答
0

不,由于选择加入方法,它不会序列化,您必须将 DataMember 显式应用于您的基类。如果您在子类中继承,数据序列化不会自动工作

于 2012-06-20T09:07:38.190 回答