PostSharp.ILParent/Child, Visitor and DisposableAnnotating an Object Model for Parent/Child Relationships (Aggregatable)
Open sandboxFocusImprove this doc

Annotating an Object Model for Parent/Child Relationships (Aggregatable)

PostSharp provides several custom attributes that you can apply to your object model to describe the parent-child relationships in a natural and concise way. The AggregatableAttribute aspect is applied to the object model classes, and the properties are marked with ChildAttribute, ReferenceAttribute and ParentAttribute custom attributes. You can also use AdvisableCollection<T> and AdvisableDictionary<TKey, TValue> classes to make your collection properties aware of the Aggregatable pattern.

Below you can find a detailed walkthrough on how to add parent-child relationships implementation into existing object models.

To apply the Aggregatable to an object model:

  1. Add the PostSharp.Patterns.Model package to your project.

  2. Add the AggregatableAttribute aspect to all base classes. Note that the aspect is inherited, so it is not necessary to explicitly add the aspect to classes that derive from a class that already has the aspect. Note also that AggregatableAttribute aspect is implicitly added by other aspects, including all threading models (ThreadAwareAttribute), DisposableAttribute and RecordableAttribute.

    Note

    It is not strictly necessary to add the AggregatableAttribute aspect to a class whose instances will be children but not parents unless you want to track the relationship to the parent using the Parent property or the ParentAttribute custom attribute in this class (see below).

  3. Annotate fields and automatic properties of all aggregatable classes with the ChildAttribute or ReferenceAttribute custom attribute. Fields or properties of a value type must not be annotated.

  4. Collections require special attention:

  5. Optionally, add a field or property to link back from the child object to the parent, and add the ParentAttribute to this field/property. PostSharp will automatically update this field or property to make sure it refers to the parent object.

    Tip

    For better encapsulation, setters of parent properties should have private visibility. In case of parent fields, the private visibility is preferred. User code should not manually set a parent field or property.

Example

In the following examples, an Invoice object owns several instances of the InvoiceLine class, therefore both classes must be annotated with AggregatableAttribute. However, the Invoice does not own the Customer to which it is associated, so the Customer class does not need the custom attribute.

Note that in the constructor of the Invoice class, we assign an AdvisableCollection<T> to the Lines field instead of a List.

[Aggregatable]
public class Invoice
{
  public Invoice()
  {
     this.Lines = new AdvisableCollection<InvoiceLine>();
  }

  [Reference]
  public Customer Customer { get; set; }

  [Child]
  public IList<InvoiceLine> Lines { get; private set; }

  [Child]
  public Address DeliveryAddress { get; set; }
}                

[Aggregatable]
public class InvoiceLine
{
  [Reference]
  private Product product;

  public decimal Amount { get; set; }

  [Parent]
  public Invoice ParentInvoice { get; private set; }
}     

[Aggregatable]
public class Address
{
}

public class Customer
{
}

See Also

Reference

AggregatableAttribute
ParentAttribute
ChildAttribute
ReferenceAttribute
AdvisableCollection<T>
AdvisableDictionary<TKey, TValue>
Other Resources

Rule-Based Annotation