Describe aggregation's mechanisms and how they work.
What aggregation does in MS COM
Question: Describe the mechanism of aggregation in Microsoft COM and how does it work?
Introduction: Component Object Model (COM) is a binary-interface standard introduced by Microsoft that allows inter-process communication and dynamic object creation in a large range of programming languages. A foundational concept in COM is the notion of reusability, facilitated by mechanisms such as aggregation and containment. This article delves into the mechanism of aggregation, elucidating its underlying principles and operational methodology.
Basic Tenets of COM Aggregation: Aggregation is a mechanism that allows one object (the outer object) to expose the interfaces of another object (the inner object) as if they were its own. It's a means to achieve a type of inheritance, allowing objects to be built by reusing functionality from other objects. The distinction between aggregation and the related concept of containment is paramount: while containment involves one object embedding another and manually implementing and forwarding calls to the encapsulated object, aggregation allows the outer object to delegate calls directly to the inner object, making the inner object's interfaces appear as though they belong to the outer object.
Initialization: When the outer object is being instantiated, it's responsible for creating the inner object. The outer object does this by calling the CoCreateInstance function but specifies the CLSCTX_INPROC_SERVER | CLSCTX_INPROC_HANDLER context flag and its own IUnknown pointer.
Interface Delegation: The inner object's interfaces are accessible through the outer object's IUnknown interface. Whenever a client queries the outer object for an interface that it doesn’t implement natively, but which the inner object supports, the outer object can simply delegate the call to the inner object.
Reference Counting: COM objects use reference counting to manage their lifetimes. When aggregation is in play, it's crucial that only the outer object's reference count is incremented or decremented. Both the outer and inner objects share the same reference count. When a client releases an interface pointer, it's the outer object's responsibility to manage the reference count, ensuring that when it drops to zero, both the outer and inner objects are destroyed.
Interface Exposure: Not all interfaces of the inner object might be relevant or safe to expose to clients. The outer object can choose which interfaces it wishes to expose and can deny queries for interfaces that should remain hidden.
Advantages and Limitations: Advantages:
Reusability: Aggregation provides a direct mechanism to reuse functionality without code duplication.
Transparency: Clients interact with the outer object, oblivious to the fact that some of the interfaces might be implemented by an aggregated inner object.
Complexity: Aggregation can introduce intricacies, especially concerning reference counting and interface delegation.
Reduced Control: The outer object has limited control over the inner object's implementations, which might not always align with desired functionalities or behaviors.
Conclusion: In the realm of Microsoft COM, aggregation stands as a potent mechanism, enabling object reuse and facilitating a form of inheritance. By allowing an outer object to expose and delegate interface calls to an inner object, aggregation enriches the object-oriented paradigm that COM seeks to implement. However, like all tools, its power comes with complexity, necessitating careful design considerations.
Aggregation provides a mechanism that allows you compose several COM objects into one larger composite COM object. Unlike containment/delegation, where we have a multilevel client/server relationship (that is, the outer COM object acts like a client to the inner COM object), aggregated objects combine with the outer COM object (the aggregator) into what appears to be one COM object that supports the interfaces implemented in all the objects. The following diagram illustrates an aggregation of two COM objects.
Notice how the inner object's interfaces are directly exposed as if they are part of the outer object.
A client holding a pointer to an inner object's interface has a pointer directly into the inner object. Yet the client thinks the interface pointer belongs to the outer object
Using aggregation, we can create compositions of several COM objects (not just two). For example, suppose we have components called FindFile, ReadWriteFile, and ArchiveFile. FindFile is an aggregation of two components: LocalFindFile and RemoteFindFile. We can create a FileManager component that reuses the interfaces provided by each component. The following diagram depicts this aggregation of objects.
In the picture above, FileManager supports eight interfaces. Besides its IUnknown (depicted at the top), it gets three interfaces from FindFile, one from ReadWriteFile, two from ArchiveFile, and one of its own interfaces (depicted on the bottom left). Additionally, FindFile is an aggregate with three interfaces: one of its own, one from LocalFindFile, and one from RemoteFindFile.
A client using the FileManager component sees FileManager as implementing all these interfaces and it does not see the FindFile, ReadWriteFile, or ArchiveFile objects. The objects aggregated by FindFile, LocalFindFile and RemoteFindFile are not visible to FileManager either.