c#-DataContract序列化-基类、继承和重写

c#-DataContract序列化-基类、继承和重写,c#,inheritance,serialization,overriding,datacontract,C#,Inheritance,Serialization,Overriding,Datacontract,大家好, 我是一名独立的游戏开发人员,过去主要与XNA合作,在另一个极端,还与商业工具集合作。然而,XNA的应用范围非常有限,我正在构建一个跨平台的抽象层来针对多个平台 长话短说,我需要比[Serializable]更广泛的可访问性的xml序列化,并且我被指向了数据契约。我已经做了很多研究,但是找不到关于系统的一些基础知识的好信息,比如继承和重写 我的问题的关键是 [DataContract] public class Node { private string name; p

大家好,

我是一名独立的游戏开发人员,过去主要与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; } }
}

“Complex”中的“Value”会被序列化吗?一些答案表明,如果没有使用[DataMember]标记,所有属性都将被序列化。如果是这样,基类的[IgnoreDataMember]属性是否有任何关系?

您应该在契约应公开的属性上包含
[DataMember]
属性

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

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

注意,Windows通信基础(WCF)使用数据契约序列化程序来序列化和反序列化数据(将其转换为XML)。所以实际上您仍然在使用Xml序列化

据我所知,DataContract是一种“选择性加入”的序列化方法,也就是说,除非对内容进行修饰,否则不会对其进行序列化(告诉序列化程序您要对其进行序列化)

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

使用标准的Serializable属性,序列化程序将查看所有字段,只忽略那些标记为非序列化的字段

这里有一些例子:

有关序列化内容的信息以及所发生情况的大致概述,请查看本页的“注释”部分:

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


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

一些答案中给出的一些想法不清楚。请让我把它们清理一下。首先,使用DataContract的序列化程序可用于序列化未使用DataContract修饰的类型。你只需要通知serailizer就可以了

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

var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(MyClass), new Type[] { Type1, Type2, Type3 });
序列化程序将自动序列化类型的每个公共字段和属性。有关详细信息,请参阅

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

因此,必须用
DataMemberAttribute
修饰要序列化的每个字段或属性。这意味着
IgnoreDataMemberAttribute
是无用的。如果是,序列化程序将不会查找它,因为任何未标记为
DataMemberAttribute
的内容都将被自动忽略

未标记的DataContractAttribute类型
如前所述,序列化未应用DataContractAttribute的类型时,将序列化每个公共属性或字段。因此,此处使用
IgnoreDataMemberAttribute
来防止对属性或字段进行序列化。

您还需要为typeof(节点)使用KnowType FancyNode,因为它是XML(基于数据)…如果不添加DataMember,则所有的道具都将被视为DataMembers(在.NET 4中(我猜)),但是如果你做了一些,没有的将不会被序列化。@L.B我很乐意尝试,但我想我可能会从其他人的经验中受益。很快我将需要自己探索实现,但如果我能做好更好的准备,这可能会省去很多挫折。@Jocke那么你必须对一个类的所有“基类”使用KnowType吗?我的印象是,您只需要将其用于数据成员可能包含继承类的反序列化实例的情况?取决于您希望如何使用类关系,请参阅,谢谢,我认为我在框架的其他方面的经验稍微偏离了我的研究方向。你提供的链接非常有用。示例链接已经失效,如果有人有替代者,那就太好了!稍后(晚餐后!)我会用一些例子更新答案。了解更多关于WCF工作原理的信息很有趣,感谢您澄清了[DataMember]的问题。在我做的研究中,有很多相互矛盾的报告。