After you have Annotating an Object Model for Parent/Child Relationships (Aggregatable), you will want to make use of it.
Both the ChildAttribute and ParentAttribute can be used to declare parent-child relationships for other patterns such as Undo/Redo (RecordableAttribute) or threading models (ImmutableAttribute, FreezableAttribute, ...).
You can also use the Aggregatable pattern from your own code. The functionalities of this pattern are exposed by the IAggregatable interface, which all aggregatable object automatically implement. This interface allows you to execute a Visitor method against all child objects of a parent.
In the following example, we see how to implement recursive validation for an object model. We will assume that the InvoiceLine
and Address
line implement an IValidatable
interface.
To enumerate all child objects of a parent:
Cast the parent object to the IAggregatable interface.
var invoice = new Invoice(); IAggregatable aggregatable = (IAggregatable) invoice;
Note
The IAggregatable interface will be injected into the
Invoice
class after compilation. Tools that are not aware of PostSharp may incorrectly report that theInvoice
class does not implement the IAggregatable interface. Instead of using the cast operator, you can also use the Cast<TSource, TTarget>(TSource) method. This method is faster and safer than the cast operator because it is verified and compiled by PostSharp at build time.
Note
If you are attempting to access IAggregatable members on either AdvisableCollection<T> or AdvisableDictionary<TKey, TValue> you will not be able to use the cast operator or the Cast<TSource, TTarget>(TSource) method. Instead, you will have to use the QueryInterface<T>(object, bool) extension method.
Invoke the VisitChildren(ChildVisitor, ChildVisitorOptions, object) method and pass a delegate to the method to be executed.
var invoice = new Invoice(); IAggregatable aggregatable = invoice.QueryInterface<IAggregatable>(); int errors = 0; bool isValid = aggregatable.VisitChildren( (child, childInfo) => { var validatable = child as IValidatable; if (validatable != null) { if ( !validatable.Validate() ) errors++; } return true; });
Note
The visitor must return a
true
to continue the enumeration andfalse
to stop the enumeration.
See Also
Reference
AggregatableAttribute
ParentAttribute
ChildAttribute
IAggregatable
VisitChildren(ChildVisitor, ChildVisitorOptions, object)
Cast<TSource, TTarget>(TSource)
QueryInterface<T>(object, bool)