IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Delphi Discussion :

Retrouver le vrai type d'une interface en paramètre de fonction


Sujet :

Langage Delphi

  1. #1
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut Retrouver le vrai type d'une interface en paramètre de fonction
    Bonjour

    C'est peut-être évident mais je cale.

    J'ai une dll avec plusieurs interfaces.
    Pour chacune de ces interfaces j'ai une procédure spécifique qui utilise un callback pour renvoyer un type d'interface à la fois.

    J'aimerais rajouter une procedure qui renvoie n'importe quelle de ces interfaces et que le programme appelant puisse définir de quelle interface il s'agit. Un genre de

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    if InterfaceRecue is IInterface1 then ...
     
    else if InterfaceRecue is IInterface25 then ...
     
    etc.
    Sauf que que le is ne passe pas pour une interface.

    Possible ou pas ?

  2. #2
    Modérateur
    Avatar de tourlourou
    Homme Profil pro
    Biologiste ; Progr(amateur)
    Inscrit en
    Mars 2005
    Messages
    3 940
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 62
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Biologiste ; Progr(amateur)

    Informations forums :
    Inscription : Mars 2005
    Messages : 3 940
    Billets dans le blog
    6
    Par défaut
    Ceci devrait le permettre : if Supports(InterfaceRecue, IInterface1) then et même de récupérer l'interface, avec le risque exposé dans le warning
    Delphi 5 Pro - Delphi 11.3 Alexandria Community Edition - CodeTyphon 6.90 sous Windows 10 ; CT 6.40 sous Ubuntu 18.04 (VM)
    . Ignorer la FAQ Delphi et les Cours et Tutoriels Delphi nuit gravement à notre code !

  3. #3
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 100
    Par défaut
    Ecrit sur le forum, j'ai pas Delphi sous la main, donc c'est plein de faute
    J'ai beaucoup joué en C++Builder sur les interfaces entre plusieurs DLL, peu en Delphi
    Un peu de lecture [C++\Delphi] Interface, Héritage et Supports !
    Cependant même si j'ai eu plus de 100 interfaces (comme évoquée ici), je n'ai jamais eu besoin de faire un "case of", chaque interface était associé à une fonctionnalité logicielle d'un hardware, donc beaucoup de Supports pour savoir ce qui était possible ou pas pour tel ou tel périphérique.

    Etudie le code de FMX.Platform.TPlatformServices.SupportsPlatformService
    C'est plein d'interface, il y a peut-être des choses qui pourraient t'intéresser pour sur comment utiliser les interfaces au mieux, c'est pour FMX mais je parle surtout de la façon de coder qui reste un concept POO valable pour autre chose.



    Tu devrais faire une pattern strategie avec un TCallBack = procedure(AInterface: IInterface);

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    type
      TInterfaceCallBackRegistry = class(TDictionay<TGUID, TCallBack>)
      public
        procedure CallBack(AInterface: IInterface);
        function IsRegisteredGUID(AInterface: IInterface; out AGUID: TGUID): Boolean;
      end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Registry := TInterfaceCallBackRegistry.Create();
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    procedure TInterfaceCallBackRegistry.CallBack(AInterface: IInterface);
    var
      it: TPair<TGUID, TCallBack>;
      intf: IInterface;
    begin
      for it in Self do
      begin
        if Supports(AInterface, it.Key, intf) then
       begin
         it.Value(intf);
         Exit;
       end;
      end;
    end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    const
       IID_IInterface1 = '{00000001-0001-0001-0001-000000000001}'
    type
      IInterface = interface
        [IID_IInterface1] // si la constante passe pas ['{00000001-0001-0001-0001-000000000001}']
        procedure Truc;
        // ...
      end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    const
       IID_IInterface25 = '{00000025-0025-0000-0025-000000000025}'
    type
      IInterface25 = interface
        [IID_IInterface25] // si la constante passe pas ['{00000025-0025-0000-0025-000000000025}']
        procedure Machin;
        // ...
      end;
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Registry.Add( StringToGUID(IID_IInterface1), MonCodePour1); // IID_IInterface1 une constante chaine TGUID, celui associé, faudra peut-être mettre @MonCodePour1 
    Registry.Add( StringToGUID(IID_IInterface25), MonCodePour25);
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    procedure MonCodePour1(AInterface: IInterface);
    begin
    end;
     
    procedure MonCodePour25(AInterface: IInterface);
    begin
    end;
    Et ton if if if devient :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Registry.CallBack(InterfaceRecue)
    ;



    tu peux aussi profiter des astuces de compilateur Delphi

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    var
      LGUID: TGUID;
    begin
      GUID := IInterface;
      ShowMessage(GUIDToString(LGUID));
    la Conversion tu type IInterface vers TGUID est implicite, cependant, je ne sais plus si cela fonctionne avec un référence d'interface, à TESTER !


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    function  TInterfaceCallBackRegistry.IsRegisteredGUID(AInterface: IInterface; out AGUID: TGUID): Boolean;
    begin
      AGUID := AInterface; // c'est référence d'interface IInterface et non le type IInterface, je ne sais pas si l'astuce fonctionne dans ce cas.
      Result := Self.ContainsKey(AGUID);
    end;
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  4. #4
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    Citation Envoyé par tourlourou Voir le message
    Ceci devrait le permettre : if Supports(InterfaceRecue, IInterface1) then et même de récupérer l'interface, avec le risque exposé dans le warning
    Merci ! Je ne connaissais pas Supports. Je cherchais quelque chose comme implement().
    ça va bien m'aider dans un premier temps.

  5. #5
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    @@ShaiLeTroll

    J'aime beaucoup ta méthode. Je n'ai pas une centaine d'interface mais une bonne trentaine quand même.
    Ce sera bien plus court et aussi plus facilement extensible avec ce que tu proposes.
    En fait, j'utilise déjà un Callback pour chaque interface mais pas du tout de cette façon.
    J'ai une interface qui gère la lecture d'un fichier compliqué et pour chaque section du fichier, j'ai une procédure spécifique pour chaque interface.

    Exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    procedure IReader.ListSection1(OnReturnSection1: ReturnSection1);
    begin
      .. p pour chaque ligne trouvée,
      OnReturnSection1(ISection1);
    end;
    Ce qui m'oblige effectivement à faire soit tri dans l'application appelante si je fais un truc comme

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    procedure IReader.ListAny(OnReturnAny: ReturnAny);
    Ta méthode me demandera un peu plus de code et d'efforts aujourd'hui mais sera plus efficace et réutilisable pour d'autres fichiers du même genre.

    Merci pour ta réponse.
    Si j'ai un souci pour l'implémentation, je reviendrai quémander un conseil

  6. #6
    Expert éminent
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    14 100
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 14 100
    Par défaut
    Ah oui, je faisais cela avec des Record ce genre de fichier aux enregistrements de forme variable : le format NX CCAM en 2004 avec un bon vieux "case of" sur le numéro de header et selon le type un second niveau de "case of", voire un troisième niveau, tout à coup de transtypage de record pour décoder le fichier sans effort.

    Pour les fichiers binaires ou texte à longueur fixe
    Je sépare maintenant souvent le Reader, son seul but est de produire des record, rien de plus, c'est purement technique, cela évite les Copy(N, M) qui sont sources de problème.
    Ensuite, par dessus j'ai des objets métiers qui exploite le Reader (conversion, contrôle de cohérence, règle de métier, workflow ...) qui en ressortent des objets plus facile à manipuler

    Et j'ai déjà géré du versionning avec cette méthode pour être capable de lire plusieurs versions du même format de fichier, seul le reader change, les objets métiers restent les mêmes, et justement là entre parfois des Interface pour gérer des extensions (souvent les données absentes sont gérées par des valeurs neutres ou par défaut)
    Aide via F1 - FAQ - Guide du développeur Delphi devant un problème - Pensez-y !
    Attention Troll Méchant !
    "Quand un homme a faim, mieux vaut lui apprendre à pêcher que de lui donner un poisson" Confucius
    Mieux vaut se taire et paraître idiot, Que l'ouvrir et de le confirmer !
    L'ignorance n'excuse pas la médiocrité !

    L'expérience, c'est le nom que chacun donne à ses erreurs. (Oscar Wilde)
    Il faut avoir le courage de se tromper et d'apprendre de ses erreurs

  7. #7
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    C'est bien ça. Ce sont des fichiers avec des sections contenant des enregistrements de taille fixe.
    Ca porte aussi un autre nom pour les échanges standardisés entre compagnie d'assurance par exemple mais je ne me souviens plus du nom .
    Là, les lignes peuvent être composées de nombreux éléments et je devais trouver une solution pour sortir la lecture des données du programme principal déjà bien assez compliqué.

  8. #8
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut


    Ben pour un code soit-disant plein de fautes parce qu'écrit hors Delphi, ça mérite 9,9 / 10.
    Il manquait uniquement un r dans TDictionary et un ; à la fin d'une déclaration.

    Je te savais déjà parmi les meilleurs mais là, chapeau bas !

    J'ai fait un petit proto pour bien appréhender le système et ça fonctionne.
    Il ne reste plus qu'à intégrer le système à mon code existant.

    La seule chose que Delphi refuse c'est le "AGUID := AInterface;" dans IsRegisteredGUID
    Erreur de types incompatibles.
    Mais ça fonctionne sans, donc pas grave du tout.

    Merci encore

  9. #9
    Membre Expert

    Homme Profil pro
    Retraité
    Inscrit en
    Novembre 2007
    Messages
    3 530
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Novembre 2007
    Messages : 3 530
    Par défaut
    J'ai oublié de préciser que le GUID dans une constante, ça fonctionne.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Envoyer un type via une interface RMI ?
    Par spooli dans le forum Entrée/Sortie
    Réponses: 4
    Dernier message: 30/05/2011, 20h48
  2. Contenu d'une variable et paramètres de fonction
    Par antrax2013 dans le forum Langage
    Réponses: 7
    Dernier message: 31/03/2010, 10h58
  3. une structure en paramètre de fonction
    Par nikita_sophie dans le forum Débuter
    Réponses: 68
    Dernier message: 02/09/2008, 10h55
  4. Passage d'une interface en paramètre de méthode COM
    Par sylvain.cool dans le forum C++
    Réponses: 11
    Dernier message: 18/04/2008, 14h15

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo