Duration (Pacific Standard Time):
To (Pacific Standard Time):
Impact:
  • None
User Action:
  • None

Aggregation

Aggregation is the object reuse mechanism in which the outer object exposes interfaces from the inner object as if they were implemented on the outer object itself. This is useful when the outer object delegates every call to one of its interfaces to the same interface in the inner object. Aggregation is available as a convenience to avoid extra implementation overhead in the outer object in this case. Aggregation is actually a specialized case of containment/delegation.

Aggregation is almost as simple to implement as containment is, except for the three IUnknown functions: QueryInterface, AddRef, and Release. The catch is that from the client's perspective, any IUnknown function on the outer object must affect the outer object. That is, AddRef and Release affect the outer object and QueryInterface exposes all the interfaces available on the outer object. However, if the outer object simply exposes an inner object's interface as its own, that inner object's IUnknown members called through that interface will behave differently than those IUnknown members on the outer object's interfaces, an absolute violation of the rules and properties governing IUnknown.

The solution is that aggregation requires an explicit implementation of IUnknown on the inner object and delegation of the IUnknown methods of any other interface to the outer object's IUnknown methods.

Creating Aggregable Objects

Creating objects that can be aggregated is optional; however, it is simple to do and provides significant benefits. The following rules apply to creating an aggregable object:

  • The aggregable (or inner) object's implementation of QueryInterface, AddRef, and Release for its IUnknown interface controls the inner object's reference count, and this implementation must not delegate to the outer object's unknown (the controlling IUnknown).
  • The aggregable (or inner) object's implementation of QueryInterface, AddRef, and Release for its other interfaces must delegate to the controlling IUnknown and must not directly affect the inner object's reference count.
  • The inner IUnknown must implement QueryInterface only for the inner object.
  • The aggregable object must not call AddRef when holding a reference to the controlling IUnknown pointer.
  • When the object is created, if any interface other than IUnknown is requested, the creation must fail with E_NOINTERFACE.

The following code fragment illustrates a correct implementation of an aggregable object by using the nested class method of implementing interfaces:

No code example is currently available or this language may not be supported.

Aggregating Objects

When developing an aggregable object, the following rules apply:

  • When creating the inner object, the outer object must explicitly ask for its IUnknown.
  • The outer object must protect its implementation of Release from reentrancy with an artificial reference count around its destruction code.
  • The outer object must call its controlling IUnknown Release method if it queries for a pointer to any of the inner object's interfaces. To free this pointer, the outer object calls its controlling IUnknown AddRef method, followed by Release on the inner object's pointer.
    No code example is currently available or this language may not be supported.
    
  • The outer object must not blindly delegate a query for any unrecognized interface to the inner object, unless that behavior is specifically the intention of the outer object.

Related topics

Containment/Delegation