c# - DataContract Serialization - Base Classes, Inheritance and Overrides
Asked Answered
P

4

9

Good day everyone,

I'm an independent game developer who has, in the past, primarily worked with XNA and, at the other extreme, commercial toolsets. The reach of XNA is pretty limited, however, and I'm building a cross-platform abstraction layer to target multiple platforms.

To cut a long story short, I've needed xml serialization that's accessible more broadly than [Serializable], and I've been pointed to data contracts. I've been doing a lot of research, but can't find any good information about some of the basics of the system, pertaining to inheritance and overrides.

The crux of my question is...

[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; } }
}

If I serialize a 'FancyNode', will 'Rotation' be properly serialized, and will 'Name' be serialised?

Follow-up Question: I meant to ask earlier, but couldn't recall at the time. How does the serializer handler overriden [IgnoreDataMember] properties? For example...

[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; } }
}

Would 'Value' in 'Complex' be serialized? Some answers are suggesting that if no [DataMember] tags are used, all properties will be serialized. If so, does the [IgnoreDataMember] attribute of the base class have any bearing?

Plashy answered 20/6, 2012 at 8:40 Comment(5)
You also need to FancyNode with KnowType for typeof(Node) since it's XML (data based)...Doubleripper
If you dont add DataMember all props will be treated as DataMembers (in .NET 4 (i guess)), but if you make some the ones without will not be serialized.Doubleripper
@L.B I would be happy to try, but I thought I might benefit from the experience of others. Shortly I will need to explore the implementation myself, but if I can be better prepared it might save much frustration.Plashy
@Doubleripper So do you have to use KnowType for all 'base classes' of a class? I had the impression you only needed to use that for cases in which a data member might include deserializing instances of inherited classes?Plashy
Depends on how you want to use the class relationship, see msdn.microsoft.com/en-us/library/ms730167.aspxDoubleripper
E
6

As far as I know, DataContract is an 'opt-in' serialization method, i.e. stuff isn't serialized unless you decorate it (tell the serializer you want to serialize it)

So for the above example, you would need to add [DataMember] to the properties you wanted to serialize

With the standard Serializable attribute, the serializer looks at all fields and only ignores those which you mark as NonSerialized

Some examples here:

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

Check the notes section on this for info on what gets serialized and a rough outline of what happens:

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

Edit: Also I can't see any reason why any of the fields once marked as [DataMember] wouldn't be serialized properly. The DataContract method of serialization can also deal with circular references - something that other serialization sometimes has trouble with:

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

Endicott answered 20/6, 2012 at 8:47 Comment(3)
Thanks, I think my experiences with other aspects of the framework had skewed the direction of my research a little. The links you supplied have been very helpful.Plashy
Example link is dead, if anyone has a replacement, that would be great!Farley
Ill update the answer with some examples later on (after dinner!)Endicott
L
7

Some thoughts presented in a few answers are unclear. Please let me clear them up. First, the serializer that uses DataContract can be used to serialize types that are not decorated with DataContract. You only need to inform the serailizer about them.

For example, the DataContractJsonSerializer class will serialize a type into a JSON object (usually a string.) All you need to tell it is the type of object you're serializing, and then any other types it may reference:

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

The serializer will automatically serialize each public field and property of the type. For more information, see http://msdn.microsoft.com/en-us/ms733127

DataContractAttribute Marked Types

Once you mark a type with the DataContractAttribute, you turn that type into an automatically known type (that you don't need to provide as a child type) and you turn it into the properties and fields into opt-in mode.

Therefore, you must decorate each field or property you want to be serialized with the DataMemberAttribute. This means that the IgnoreDataMemberAttribute is useless. It is, the serializer will not look for it, since anything not marked with the DataMemberAttribute is automatically ignored.

Unmarked DataContractAttribute Types

When serializing a type that does not have the DataContractAttribute applied, as previously stated, each public property or field will be serialized. Therefore, the IgnoreDataMemberAttribute is used here to prevent a property or field from being serialized.

Ligni answered 5/12, 2013 at 5:16 Comment(0)
E
6

As far as I know, DataContract is an 'opt-in' serialization method, i.e. stuff isn't serialized unless you decorate it (tell the serializer you want to serialize it)

So for the above example, you would need to add [DataMember] to the properties you wanted to serialize

With the standard Serializable attribute, the serializer looks at all fields and only ignores those which you mark as NonSerialized

Some examples here:

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

Check the notes section on this for info on what gets serialized and a rough outline of what happens:

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

Edit: Also I can't see any reason why any of the fields once marked as [DataMember] wouldn't be serialized properly. The DataContract method of serialization can also deal with circular references - something that other serialization sometimes has trouble with:

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

Endicott answered 20/6, 2012 at 8:47 Comment(3)
Thanks, I think my experiences with other aspects of the framework had skewed the direction of my research a little. The links you supplied have been very helpful.Plashy
Example link is dead, if anyone has a replacement, that would be great!Farley
Ill update the answer with some examples later on (after dinner!)Endicott
T
1

You should include the [DataMember] attribute on properties that should be exposed by the contract.

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

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

Note that Windows Communication Foundation (WCF) uses the Data Contract Serializer to serialize and deserialize data (convert it to and from XML). So actually you are still using Xml Serialization.

Tinsmith answered 20/6, 2012 at 8:46 Comment(1)
It's interesting to know a little more about how the WCF works, and thanks for clearing up the [DataMember] matter. There were a lot of conflicting reports in the research I did.Plashy
C
0

No it wont serialize because of Opt-In approach, you have to explicitly apply DataMember to your base class. Data Serialization does not work automatically in case you Inherit in Child Class

Conversion answered 20/6, 2012 at 9:7 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.