Pour être en mesure de vérifier si une instance implémente une interface donnée, cette interface doit avoir un GUID défini. Alors, ajoutez un guid à votre interface (vous aurez également besoin de ce guid dans un const ou variable de sorte que vous pouvez refernce ultérieurement dans le code):
const
IID_Handle: TGUID = '{0D3599E1-2E1B-4BC1-ABC9-B654817EC6F1}';
type
IHandle<TMessage> = interface
['{0D3599E1-2E1B-4BC1-ABC9-B654817EC6F1}']
procedure Handle(AMessage: TMessage);
end;
(Vous ne devriez pas utiliser mon guid, il est juste un exemple .. appuyez sur ctrl + shift + G pour générer un nouveau guid dans l'IDE).
vérifier ensuite si l'abonné enregistré supporte cette interface:
// LTarget:= LReference as IHandle; // <-- Wish this would work
if Supports(LReference, IID_Handle, LTarget) then
LTarget.Handle(AMessage);
Cependant, cela ne prend pas la partie générique de l'interface en compte, il vérifie que le GUID.
Vous aurez donc besoin de plus de logique pour vérifier si la cible prend réellement en charge le type de message. Etant donné que vous avez affaire à des classes qui implémenteront une interface, et devraient donc dériver de TInterfacedObject (ou une interface compatible avec cette classe), vous devriez garder toutes les références à l'objet créé dans les variables d'interface, donc changer la liste des sous-traitants à partir d'une référence à TObjects 'à l'une des IInterfaces'. Et il y a une classe spécifique pour cela aussi:
FSubscribers: TInterfaceList;
Bien sûr, vous devrez changer la signature des fonctions/désabonnement vous abonner aussi:
procedure Subscribe(AInstance: IInterface);
procedure Unsubscribe(AInstance: IInterface);
Je pense une meilleure façon serait être de sortir le générique de l'interface IHandle. De cette façon, vous pouvez faire en sorte que tous les abonnés implémentent l'interface IHandler de base en changeant la signature subscribe/unsibscribe pour prendre IHandler au lieu de IInterface. IHandler peut alors conserver la fonctionnalité requise pour déterminer si l'abonné prend en charge le type de message donné ou non.
Cela sera laissé comme un exercice au lecteur. Vous pouvez commencer avec ma petite application de test (D2010) que vous pouvez télécharger à partir de My Test App.
N.B. L'application de test explore la possibilité d'utiliser des génériques dans l'interface et tombera probablement en panne lors de la publication d'événements. Utilisez le débogueur en une seule étape pour voir ce qui se passe.Je ne plante pas lors de la publication de l'entier 0, ce qui semble fonctionner. La raison en est que les gestionnaires Int et String seront appelés quel que soit le type d'entrée à publier (comme indiqué plus haut).
Notez que [QualityCentral a été arrêté] (https://community.embarcadero.com/blogs/entry/quality-keeps-moving-forward) Donc, vous ne pouvez plus accéder aux liens 'qc.embarcadero.com'. Si vous avez besoin d'accéder aux anciennes données de QC, regardez [QCScraper] (http://www.uweraabe.de/Blog/2017/06/09/how-to-save-qualitycentral/). –