I have noticed that numerous books, etc. on COM point out that it is relatively easy to implement an object that can be used as an inner object in COM aggregation. However, unless I am missing something, it seems that aggregation can only be successful in extremely limited scenarios and thus support for it should only be provided when such a scenario is specifically recognized.
The part that troubles me is as follows. COM aggregation combines an inner object's identity with that of an outer object. The implementor of the outer object selects a subset of the inner object's interfaces and forwards requests for those interfaces to the inner object. The inner object forwards all requests for interfaces to the outer object. Now suppose that the inner object, as part of its implementation, constructs child COM objects. Presumably an interface pointer is passed to that COM object so it can communicate with its parent. The inner object has some idea of the interfaces that it implements. However the outer object might have chosen not to forward some of those interfaces. Indeed, documentation states that an outer object should not blindly forward interfaces. This seems to imply that the inner object often cannot hand away interface pointers to other COM objects unless the outer object is specifically required to forward all of those interfaces to the inner object. This is not limited to a child object scenario. Indeed, any place where the inner object implementation passes an interface pointer seem like they could be affected.
So, it appears that aggregation is not general purpose because--in cases where the inner object must communicate with other COM objects--it places strict requirements on the outer object as to which interfaces minimally must be forwarded and more interfaces cannot be added to this list in future versions of the inner object without breaking compatibility with existing outer objects that do not forward those interfaces.
Is this a correct (and seldom documented) description of the way things actually are or is there more to the story?
Found your thread languishing here, thought I'd respond. For starters, aggregation compares to encapsulation in OOP, but with some significant differences. What is nice is that little work is needed in the outer interface to expose an aggregated interface. What is not nice is that an interface needs to be designed to be aggregatable from the get-go, a requirement that OOP encapsulation doesn't have. That limits the odds where you have a COM class laying on the shelf, ready to be borged. From my own work, when facing the question whether or not to support aggregation, I've yet to answer "yes, might be useful some day". The headaches from implementing the delegating and non-delegating IUnknowns have led me to "no".
Your question about inner interfaces creating objects is easy to answer. An inner interface is not supposed to know that it got aggregated. More to the point, it cannot know who aggregated it. It can thus not know whether or not the outer is at all useful to the object or if it will properly delegate QI. Not a real problem, it can simply hand it an interface pointer to one of its own interfaces. Being aggregated does not forbid it. Only unknown interfaces need to be forwarded.
But yes, aggregation isn't very practical.
Every single COM object I've ever implemented or seen implemented has the no-aggregation check in it's create method. Most of the COM objects MSFT ships don't support aggregation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With