Чтобы иметь возможность проверить, реализует ли экземпляр данный интерфейс, этот интерфейс должен иметь определенный GUID. Итак, добавьте guid к вашему интерфейсу (вам также понадобится этот guid в const или переменной, чтобы вы могли ссылаться на него позже в коде):
const
IID_Handle: TGUID = '{0D3599E1-2E1B-4BC1-ABC9-B654817EC6F1}';
type
IHandle<TMessage> = interface
['{0D3599E1-2E1B-4BC1-ABC9-B654817EC6F1}']
procedure Handle(AMessage: TMessage);
end;
(Вы не должны использовать мой guid, это всего лишь пример. Нажмите ctrl + shift + G, чтобы сгенерировать новый guid в IDE).
Затем проверьте, поддерживает ли зарегистрированный подписчик этот интерфейс:
// LTarget:= LReference as IHandle; // <-- Wish this would work
if Supports(LReference, IID_Handle, LTarget) then
LTarget.Handle(AMessage);
Однако это не учитывает общую часть интерфейса, а только проверяет GUID.
Так что вам понадобится больше логики, чтобы проверить, действительно ли цель поддерживает тип сообщения.
Кроме того, поскольку вы имеете дело с классами, которые будут реализовывать интерфейс и, следовательно, должны наследоваться от TInterfacedObject (или совместимого интерфейса с этим классом), вы должны хранить все ссылки на созданный объект в переменных интерфейса, таким образом изменяя список подписчиков из ссылки на объекты TObjects для одного из интерфейсов. И для этого тоже есть специальный класс:
FSubscribers: TInterfaceList;
Конечно, вам придется изменить подпись и на функции подписки / отмены подписки:
procedure Subscribe(AInstance: IInterface);
procedure Unsubscribe(AInstance: IInterface);
Я думаю, что лучшим способом было бы взять универсальный интерфейс IHandle. Таким образом, вы можете обеспечить, чтобы все подписчики внедряли базовый интерфейс IHandler, изменив подпись подписки / отмены подписки, чтобы принимать IHandler вместо IInterface.
IHandler может хранить функциональность, необходимую для определения, поддерживает ли подписчик данный тип сообщения.
Это будет оставлено в качестве упражнения для читателя. Возможно, вы захотите начать с моего маленького тестового приложения (D2010), которое вы можете загрузить с My Test App .
N.B. Тестовое приложение исследует возможность использования обобщенных элементов в интерфейсе и, скорее всего, приведет к сбою при публикации событий. Используйте отладчик для одного шага, чтобы увидеть, что происходит. Я не сбой при публикации целого 0, который, кажется, работает.
Причина в том, что и Int, и String обработчик будут вызываться независимо от типа ввода для публикации (как обсуждалось ранее).