ComplexObject Class

WCF RIA Services

[WCF RIA Services Version 1 Service Pack 2 is compatible with either .NET framework 4 or .NET Framework 4.5, and with either Silverlight 4 or Silverlight 5.]

Base class for all complex objects.


Namespace:  System.ServiceModel.DomainServices.Client
Assembly:  System.ServiceModel.DomainServices.Client (in System.ServiceModel.DomainServices.Client.dll)

public abstract class ComplexObject : INotifyPropertyChanged, 
	IEditableObject, INotifyDataErrorInfo

The ComplexObject type exposes the following members.

Protected methodComplexObjectCreated an instance of the ComplexObject.

Public propertyHasValidationErrorsGets a value indicating whether this entity has any validation errors.
Protected propertyIsDeserializingGets a value indicating whether this instance is currently being deserialized.
Public propertyValidationErrorsGets the collection of validation errors for this instance.

Protected methodBeginEditBegin editing this complex object instance.
Protected methodCancelEditCancels any edits made to this instance since the last call to BeginEdit().
Protected methodEndEditCommits the edits made to this instance since the last call to BeginEdit().
Public methodEquals (Inherited from Object.)
Protected methodFinalize (Inherited from Object.)
Public methodGetHashCode (Inherited from Object.)
Public methodGetType (Inherited from Object.)
Protected methodMemberwiseClone (Inherited from Object.)
Public methodOnDeserializedMethod called after a complex object has been deserialized.
Public methodOnDeserializingMethod called when a complex object is being deserialized.
Protected methodOnPropertyChangedCalled when the property of a complex object has changed.
Protected methodRaiseDataMemberChangedCalled from a property setter to notify the framework that a data member of a complex object has changed.
Protected methodRaiseDataMemberChangingCalled from a property setter to notify the framework that a data member of a complex object is about to be changed.
Protected methodRaisePropertyChangedCalled from a property setter to notify the framework that a complex object property has changed.
Public methodToString (Inherited from Object.)
Protected methodValidateProperty(ValidationContext, Object)Validates whether the specified property value is valid for a specified ValidationContext.
Protected methodValidateProperty(String, Object)Validate whether the specified value is valid for the specified property of the current complex object.

Explicit interface implemetationPrivate methodIEditableObject.BeginEditBegin editing this instance of this complex object.
Explicit interface implemetationPrivate methodIEditableObject.CancelEditCancels the edits made to this complex object instance since the last call to IEditableObject.BeginEdit().
Explicit interface implemetationPrivate methodIEditableObject.EndEditCommits the edits made to this complex object instance since the last call to IEditableObject.BeginEdit().
Explicit interface implemetationPrivate eventINotifyDataErrorInfoErrorsChangedExplicitly implement the ErrorsChanged() event.
Explicit interface implemetationPrivate methodINotifyDataErrorInfoGetErrorsRetrieves the errors for the specified property, or the type-level errors if propertyName is null or empty.
Explicit interface implemetationPrivate propertyINotifyDataErrorInfoHasErrorsGets a value indicating whether or not the entity presently has errors.
Explicit interface implemetationPrivate eventINotifyPropertyChanged.PropertyChangedEvent raised whenever a ComplexObject property has changed.

A complex object type in WCF RIA Services is a structural custom user type that can be used like base type. The framework provides a lot of entity-like functionality such rich client code generation for complex types and much of the framework behavior for complex types is the same or very similar to that of entities. But a ComplexObject differs from an Entity in important ways. In particular, complex types do not have identities. This means that they do not have members marked with the KeyAttribute and so clients cannot do identity caching for them as it does for entities. Complex types cannot be shared or referenced from multiple parent instances and they do not support inheritance.

Assume you have an entity type Customer with a member of type Address:

public class Address
    public string AddressLine1 { get;set }
    public string City { get;set }
    public string Region { get;set }
    public string PostalCode { get;set }
    public string Country { get;set }

public class Customer
    public string CustomerID { get;set; }
    public string CompanyName { get;set }
    public string ContactName { get;set }

    public Address HomeAddress { get;set; }

These types will result in corresponding generated client types:

public class Address : ComplexObject
    public string AddressLine1 { . . . }
    public string City { . . . }
    public string Region { . . . }
    public string PostalCode { . . . }
    public string Country { . . . }

public class Customer : Entity
    public string CustomerID { . . . }
    public string CompanyName { . . . }
    public string ContactName { . . . }

    public Address HomeAddress { . . . }

Notice that Address derives from ComplexObject.

Code Generation

The client proxies generated for complex types are very similar to those generated for entities. This includes partial extensibility methods, validation metadata, etc. Code-generated complex types derive from the ComplexObject base class. The generated property setter logic for complex types members and members of complex types follows the same property patterns used for entities.


As with entities, you can apply additional metadata to your complex types on the server via buddy classes, and that metadata will flow through the system. Similarly, in cases where you’re using a Data Access layer (DAL) that supports complex types, DAL metadata will also be applied (e.g. inferring the StringLengthAttribute for members based on your Entity Framework model). Complex types participate in the metadata pipeline the same way entities do.


Property setter validation is performed for complex type members in the same way that it is for entity members. In addition, validation errors for nested complex type members propagate up the containment hierarchy. Deep submit time validation is performed on both tiers for entity complex type members. In all cases, a nested validation error will be reported as an error on each parent up the hierarchy. For example, if the Customer.ContactInfo.HomeAddress.PostalCode member is invalid, that validation error will surface in the validation errors of the Customer, ContactInfo and HomeAddress instances. The member name(s) in the ValidationResult will be pathed appropriately at each level.

Change Tracking

Singleton entity complex type members (e.g. Customer.Address) fully participate in change tracking and the rest of the Accept/RejectChanges pipeline. As nested complex type members are changed, those changes are reported up the containment hierarchically causing the parent entity to become dirty. If changes are rejected on the entity, all nested complex type changes are reverted. Conceptually, nested complex type members are treated by the system the same way top level non- complex type entity properties are.

Complex types in collection members (e.g. Customer.PhoneNumbers) are not tracked deeply. They will be deeply validated at submit time, but validation errors are not raised on the entity as members are set on complex type instances in the collection, and the parent entity isn’t tracking whether instances in the collection have been modified, added or removed. To modify the contents of a complex type collection member, a new collection instance must be assigned to the member.

Edit Sessions

Entity complex type members fully participate in entity edit sessions initiated via the IEditableObject interface. If a BeginEdit() is performed on an entity, the state snapshot for the entity includes all nested complex type state recursively. Similarly if CancelEdit()/EndEdit() are performed, the changes are applied recursively. ComplexObject itself implements IEditableObject, so you get full edit session support for complex types not hosted by entities.


Complex type members are always serialized deeply based on DataContract/DataMember annotations. This contrasts with entity associations, whose serialization is governed by the application of IncludeAttribute.

Any public static (Shared in Visual Basic) members of this type are thread safe. Any instance members are not guaranteed to be thread safe.