Data Contract Equivalence





Data Contract Equivalence

Two data contracts are considered equivalent if they have the same wire representation. This can be the case when defining the same type (but not necessarily the same version of the type), or if the two data contracts refer to two different types with the same names for the contract and the members. Equivalent data contracts are interchangeable: WCF will let any service that was defined with one data contract operate on an equivalent data contract.

The most common way of defining an equivalent data contract is to use the Name property of the DataContract or DataMember attribute to map one data contract to another. In the case of the DataContract attribute, the Name property defaults to the type's name, so these two definitions are identical:

[DataContract]
struct Contact
{...}

[DataContract(Name = "Contact")]
struct Contact
{...}

In fact, the full name of the data contract always includes its namespace as well, but as you have seen, you can assign a different namespace. In the case of the DataMember attribute, the Name defaults to member name, so these two definitions are identical:

[DataMember]
public string FirstName;

[DataMember(Name = "FirstName")]
public string FirstName;

By assigning different names to the contract and the members you can generate an equivalent data contract from a different type.

For example, these two data contracts are equivalent:

[DataContract]
struct Contact
{
   [DataMember]
   public string FirstName;

   [DataMember]
   public string LastName;
}
[DataContract(Name = "Contact")]
struct Person
{
   [DataMember(Name = "FirstName")]
   public string Name;

   [DataMember(Name = "LastName")]
   public string Surname;
}

In addition to having identical names, the types of the data members have to match.

A class and a structure that support the same data contract are interchangeable.


Serialization Order

Equivalent data contracts must serialize and deserialize their members in the same order. The default serialization order inside a type is simply alphabetical, and across class hierarchy the order is top-down. In case of a mismatch in the serialization order, the members will be initialized to their default values. For example, when serializing a Customer instance, defined as:

[DataContract]
class Contact
{
   [DataMember]
   public string FirstName;

   [DataMember]
   public string LastName;
}
[DataContract]
class Customer : Contact
{
   [DataMember]
   public int CustomerNumber;
}

the members will be serialized in the following order: FirstName, LastName, CustomerNumber.

The problem now is that combining data contract hierarchy with aliasing contracts and members might break the serialization order. For example, the following data contract is now not equivalent to the Customer data contract:

[DataContract(Name = "Customer")]
public class Person
{
   [DataMember(Name = "FirstName")]
   public string Name;

   [DataMember(Name = "LastName")]
   public string Surname;

   [DataMember]
   public int CustomerNumber;
}

because the serialization order is CustomerNumber, FirstName, LastName. To resolve this conflict, you need to provide WCF with the order of serialization by setting the Order property of the DataMember attribute. The Order property defaults to -1, meaning the default WCF ordering, but you can assign to it values indicating the required order:

[DataContract(Name = "Customer")]
public class Person
{
   [DataMember(Name = "FirstName",Order = 1)]
   public string Name;

   [DataMember(Name = "LastName",Order = 2)]
   public string Surname;

   [DataMember,Order = 3)]
   public int CustomerNumber;
}

If another member has the same value for its Order property, WCF will order them alphabetically. You can take advantage of this by assigning the same number to all members coming from the same level in the original class hierarchy, or better yet, assign them simply their level in that hierarchy:

[DataContract(Name = "Customer")]
public class Person
{
   [DataMember(Name = "FirstName",Order = 1)]
   public string Name;

   [DataMember(Name = "LastName",Order = 1)]
   public string Surname;

   [DataMember,Order = 2)]
   public int CustomerNumber;
}



 Python   SQL   Java   php   Perl 
 game development   web development   internet   *nix   graphics   hardware 
 telecommunications   C++ 
 Flash   Active Directory   Windows