Clarification sur la façon de déclarer correctement les interfaces d'interopérabilité

StackOverflow https://stackoverflow.com/questions/1618778

  •  06-07-2019
  •  | 
  •  

Question

C’est juste une question sur la façon d’écrire mon code pour une importation COM.

D'après ce que je comprends de la mise en œuvre correcte des interfaces d'interopérabilité, le critère principal est le suivant:

  1. Toutes les signatures de méthode doivent correspondre de manière compatible
  2. Les méthodes doivent apparaître exactement dans le même ordre dans l'interface .Net que dans l'interface non gérée
  3. Lorsque l'interface non managée hérite d'une autre interface non managée, l'implémentation gérée doit d'abord déclarer les membres de l'interface de niveau base, en commençant par l'interface la plus à la base.

Ma question est; que dois-je faire en ce qui concerne l'ordre d'apparition des membres, si l'interface que j'importe est héritée d'une autre interface et remplace / masque un ou plusieurs des membres de l'interface de base? Où va la déclaration du membre d'interface? Tout d'abord, où l'interface de base l'a déclaré? Ou retiré de sa position d'origine et placé là où l'interface dérivée le déclare?

[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)]
interface BaseComInterface
{
    void method1();
    void method2();
    void method3();
}

[uuid(fab51c92-95c3-4468-b317-7de4d7588254)]
interface DerivedComInterface : BaseComInterface
{
    void method1();
    void method4();
    void method5();
}

Maintenant pour le code C #:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); // do I remove this one?
    void method2();
    void method3();
    void method1(); // or this one?
    void method4();
    void method5();
}
Était-ce utile?

La solution

Avez-vous un exemple de quelqu'un qui fait cela? Bien qu'il soit parfaitement légal dans COM d'avoir le même nom pour une méthode dans une interface et dans une autre interface qui en dérive, cela rend le travail avec l'interface dérivée difficile, voire impossible, dans pratiquement tous les environnements de développement. Cela inclut la mise en oeuvre et l’appel d’objets COM en fonction de l’interface.

Il n’existe pas de substitution ou de masquage dans une interface COM. Une interface COM est simplement un contrat sur la manière dont l’interface binaire d’un objet sera mise en mémoire, les noms des méthodes de la définition de l’interface n’ont de sens, sauf pour les outils. Dans votre cas, BaseComInterface vous promet une 'table virtuelle' avec six méthodes, les trois premières correspondent aux signatures des méthodes IUnknown et les trois suivantes correspondent aux signatures des trois méthodes que vous avez données, toutes dans le bon ordre. D'autre part, DerivedComInterface promet une 'table virtuelle' comprenant neuf méthodes. Les trois premières signatures correspondent aux méthodes IUnknown, les trois suivantes correspondent aux signatures des méthodes BaseComInterface et les trois dernières correspondent aux trois méthodes propres à DerivedComInterface. Les noms de ces méthodes sont sans importance, sauf pour votre IDE, vos outils et votre compilateur qui ont besoin des noms pour trouver les pointeurs 'vtable'.

En gros, en C #, C, C ++ et quelques autres langages, pour implémenter DerivedComInterface, un des noms de méthodes doit être décoré afin de distinguer son emplacement 'vtable' de l'autre.

Pour répondre à votre question, vous ne supprimeriez aucune des deux méthodes car elles sont toutes deux nécessaires pour remplir le contrat COM:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport,  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); 
    void method2();
    void method3();
    void method1_2(); //Decorated to distinguish from base interface method.
    void method4();
    void method5();
}

Cela ignore ce qui se produirait si ces interfaces étaient dérivées d'IDispatch plutôt que d'IUnknown, un gâchis dans lequel je ne voudrais pas entrer. De plus, rappelez-vous que si votre idl définit réellement les méthodes comme renvoyant void, vous devez décorer vos méthodes C # avec l'attribut PreserveSig.

Autres conseils

Je vous suggère d'utiliser les implémentations de membres d'interface explicites éviter les conflits.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top