Data Contract Equivalence

Two data contracts are considered equivalent if they have the same wire representation—that is, if they have the same infoset schema. This can be the case if they define 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 data contract and data member names. Equivalent data contracts are interchangeable: WCF will let any service that was defined with one data contract operate with an equivalent data contract.

The most common way of defining an equivalent data contract is to use the DataContract and DataMember attributes' Name properties 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 property defaults to the member name, so these two definitions are identical:

[DataMember]
string FirstName;

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

By assigning different names to the data contract and data 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.

Tip

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

Serialization Order

In classic .NET, a subclass can define a member of the same name and type as a private member of its base class, and in turn, its own subclass can do the same:

class A
{
   string Name;
}
class B : A
{
   string Name;
}
class C : B
{
   string Name;
}

If the class hierarchy is also a data contract, this presents a problem when serializing into a message an instance of the subclass, since the message will contain multiple copies of a data member with the same name and type. To distinguish between them, WCF places the data members in the message in a particular order.

The default serialization order inside a type is simply alphabetical, and across a 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.

Of course, equivalent data contracts must serialize and deserialize their members in the same order. The problem now is that combining a data contract hierarchy with aliasing contracts and members might break the serialization order. For example, the following data contract is 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 value of 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;
}

When renaming data members, you must take care to manually change their order. Even without renaming, with a large number of data members, the sorting can quickly get out of hand. Fortunately, if another member has the same value for its Order property, WCF will order them alphabetically. You can take advantage of this behavior by assigning the same number to all members coming from the same level in the original class hierarchy, or, better yet, simply assign them their levels 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;
}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.174.253