Héritage, agrégation et relation contenant-contenu

La possibilité de réutiliser COM dans le .NET Framework est réalisée par voie d'héritage. Les types COM peuvent participer à l'héritage en tant que classe de base. Utilisez l'héritage, l'agrégation ou les modèles de relation contenant-contenu dans les situations suivantes :

Modèle

À utiliser pour

Héritage

Exposer l'objet managé comme objet externe.

Agrégation

Permettre à l'objet externe d'exposer l'implémentation par un autre objet d'une interface sans modification.

Relation contenant-contenu

Permettre à l'objet externe de modifier le comportement de l'objet interne.

Héritage

Lorsque des interfaces managées sont exposées à COM, elles étendent toujours IUnknown ou IDispatch, même quand l'interface est héritée d'une autre interface côté managé. La même règle s'applique aux interfaces de classe qui sont générées pour des classes managées.

Le .NET Framework étend le modèle COM à des fins de réutilisation en ajoutant un héritage d'implémentation. Les types managés peuvent dériver directement ou indirectement d'une coclasse COM, et plus précisément, du wrapper RCW (Runtime Callable Wrapper) généré par le runtime. Le type dérivé peut exposer l'ensemble des méthodes et propriétés de l'objet COM, ainsi que les méthodes et propriétés implémentées dans un code managé. L'objet résultant est implémenté en partie dans un code managé et en partie dans un code non managé.

Pour prétendre au titre de classe de base, la coclasse doit :

Les types managés peuvent étendre le wrapper RCW pour une coclasse habilitée et substituer les méthodes fournies par l'objet de base. Vous devez substituer toutes les méthodes de base d'une interface si vous souhaitez substituer l'une d'elles.

Un type managé hérite d'un wrapper RCW de la même façon qu'il hérite d'un objet de base managé. Dans l'exemple de code suivant, la classe managée Catapult dérive de AcmeLib.Slingshot, un type COM.

#using "AcmeLib.dll"    // Provides definition of Slingshot.

__gc class Catapult : public AcmeLib.Slingshot  // Extends the COM type.
{
    // Delegates to base implementation.
    Load() { //… };  
   
    Fire()               
    {
        // Engages in some behavior before delegating to the base 
        // implementation.
        Slingshot::Fire();
    }

    // The Aim method needs to be overridden.
    Aim() { //… }         
}
Catapult *cp = new Catapult();

// Calls derived implementation.
cp->Load();
// Calls base implementation.
cp->Aim();
// Calls derived which delegates to base.
cp->Fire();

Agrégation

Pour exposer les interfaces d'une classe COM comme si elles étaient implémentées sur une deuxième classe COM, la deuxième classe agrège la première. Un objet COM peut agréger un objet .NET, auquel cas toutes les interfaces de l'objet, y compris son interface de classe, sont disponibles via l'objet externe. L'objet .NET interne délègue les appels adressés à ses méthodes IUnknown à l'interface de contrôle IUnknown.

L'agrégation est légèrement plus complexe que la relation contenant-contenu (décrite dans la section suivante). Vous l'utilisez généralement pour permettre à l'objet externe d'exposer l'implémentation par un autre objet d'une interface sans modification. Tous les objets managés prennent automatiquement en charge l'agrégation de style COM avec l'objet managé utilisé comme objet interne. Pour agréger un objet managé, l'objet externe non managé crée l'objet interne managé en appelant CoCreateInstance, puis en passant IUnknown de l'objet externe en tant paramètre OuterUnknown. Quand une interface IUnknown externe est passée à un objet managé pendant la construction, celui-ci met en cache l'interface et l'utilise de la façon suivante :

  • L'objet externe maintient l'interface IUnknown non déléguante de IUnknown interne. L'interface IUnknown non déléguante agit comme une interface IUnknown normale ; cela signifie qu'il s'agit d'une réussite si l'objet implémente l'interface et d'un échec dans le cas contraire. L'interface IUnknown non déléguante ne transmet pas l'appel à l'objet externe.

  • Si l'objet interne est interrogé au sujet d'une interface qu'il ne prend pas en charge, l'objet interne délègue l'appel à l'interface IUnknown de l'objet externe.

  • Tous les appels aux méthodes QueryInterface, AddRef et Release de l'objet interne sont délégués à l'interface IUnknown de l'objet externe.

Ces trois comportements permettent d'agréger n'importe quel objet managé. Ce type de relation d'agrégation permet d'avoir un seul objet COM qui est implémenté en partie dans le code managé (la partie interne) et en partie dans le code non managé (la partie externe).

Relation contenant-contenu

Un objet .NET peut contenir un objet COM en important ses métadonnées dans un assembly .NET, puis en déclarant des données membres de ce type dans une autre classe. Comme avec la relation contenant-contenu COM standard, vous pouvez appeler les interfaces de l'objet COM dans vos propres implémentations de l'interface, mais l'objet contenu n'est pas exposé à l'extérieur de la classe. La relation contenant-contenu est plus simple que l'agrégation. Vous l'utilisez généralement quand l'objet externe doit modifier le comportement de l'objet interne. Pour ce faire, l'objet externe crée simplement une instance de l'objet interne dans son constructeur, puis délègue les appels à l'objet interne, le cas échéant. L'objet externe peut choisir les appels à déléguer et les appels à gérer directement. Le runtime n'impose pas de contraintes particulières aux objets en ce qui concerne la prise en charge de la relation contenant-contenu.

Un objet COM peut également contenir un objet .NET. Le comportement vis-à-vis des clients de l'objet COM est exactement le même que si l'objet contenu était un autre objet COM.

Voir aussi

Concepts

Exposition de composants COM au .NET Framework

Exposition de composants .NET Framework à COM

Autres ressources

Interopérabilité COM avancée