Ho un modulo Delphi che fornisce la funzionalità dietro un oggetto di interfaccia che altre parti del codice ottengono riferimenti anche tramite una proprietà che appartiene al modulo. Non è possibile delegare la funzionalità dell'interfaccia a un oggetto figlio poiché troppe funzionalità vengono gestite da controlli/componenti nel modulo. Non posso usare TAggregatedObject o TContainedObject per collegare la durata degli oggetti interfacciati passati al Form perché la classe TForm non eredita da TinterfacedObject e Delphi non supporta l'ereditarietà multipla quindi non posso mischiare TInterfacedObject nella catena di ereditarietà . Questa situazione può portare a violazioni di accesso se un modulo viene distrutto mentre un altro codice contiene uno dei riferimenti all'interfaccia distribuiti dal modulo. Qualcuno può pensare ad una buona soluzione a questo problema?Un modo sicuro in Delphi per un modulo per distribuire oggetti di interfaccia legati alla sua durata?
risposta
È possibile delegare l'interfaccia per un oggetto figlio, basta avere quell'oggetto contiene un puntatore interno al modulo in modo che possa accedere ai controlli del modulo in caso di necessità, non è diverso allora si sta già facendo in questo momento.
È possibile utilizzare TAggregateObject
o TContainedObject
per le proprie esigenze. Non richiedono che il modulo derivi da TInterfacedObject
. Tutto quello che richiedono è un puntatore IInterface
interfaccia, e TComponent
deriva da IInterface
(e sostituisce il _AddRef()
e _Release()
per disattivare il conteggio di riferimento), in modo da poter passare la forma stessa (essendo discendente TComponent
) come IInterface
puntatore richiesto.
Questo lascia l'unico problema rimanente: la chiusura del modulo mentre i riferimenti di interfaccia attivi sono trattenuti da un altro codice. La soluzione più semplice è quella di 1) riscrivere quel codice per non mantenere tali riferimenti mentre il modulo si sta chiudendo, oppure 2) non consentire al modulo di chiudersi fino a quando questi riferimenti non sono stati rilasciati.
Nota: Ciò funzionerà solo se il consumatore è anche derivato da TComponent.
Per evitare i riferimenti morti è possibile interrogare il IInterfaceComponentReference
(disponibile su ogni TComponent) dal modulo, chiami GetComponent
su tale interfaccia e collegare se stessi al FreeNotification
della tornata Componente/Modulo.
Quello che succede ora è: quando il modulo viene distrutta ne informa tutte le "listners" che la sua intenzione di distruggere se stessa chiamando il metodo Notification
sul consumatore con se stessa (forma) come AComponent
e opRemove
come il funzionamento. In questo modo è possibile annullare il riferimento all'interfaccia. Ma attenzione che i riferimenti agli oggetti e i riferimenti all'interfaccia non devono essere uguali. Assicurati inoltre di chiamare RemoveFreeNotification
quando non hai più bisogno della notifica per evitare chiamate inutili.
TSomeConsumer = class(TComponent)
private
FInterfaceToAService: ISomeInterface;
protected
procedure Notification(AComponent: TComponent; Operation: TOperation); override;
public
procedure SetService(const Value: ISomeInterface);
end;
procedure TSomeConsumer.Notification(AComponent: TComponent; Operation: TOperation);
begin
inherited;
if (Operation = opRemove) and (AComponent = TObject(FInterfaceToAService)) then
SetService(nil); // Takes care of niling the interface as well.
end;
procedure TSomeConsumer.SetService(const Value: ISomeInterface);
var
comRef: IInterfaceComponentReference;
begin
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.RemoveFreeNotification(self);
FInterfaceToAService := Value;
if Supports(FInterfaceToAService, IInterfaceComponentReference, comRef) then
comRef.GetComponent.FreeNotification(self);
end;
Bello! Non lo sapevo. Potresti espandere un po 'la tua affermazione - "Ma tieni presente che i riferimenti a oggetti e i riferimenti all'interfaccia non devono essere uguali."? –
Bene, diversi motivi: a) è possibile eseguire un'implementazione personalizzata di 'QueryInterface' che può restituire un nuovo oggetto interfacciato su ogni chiamata. b) In secondo luogo è possibile delegare l'interfaccia a una proprietà (Win32), che potrebbe creare nuovamente un nuovo oggetto ogni volta. c) L'implementazione di 'TObject.GetInterface' aggiunge un'interfacciaOffset all'indirizzo.(Ma questi interni sono, purtroppo, al di là della conoscenza maggio) La recente introduzione (Delphi 2010) Interfaccia di opporsi fusione è sostanzialmente fatto interrogando un'interfaccia marcatore, che restituisce l'indirizzo entrata dell'oggetto. –
Cosa succederà se i riferimenti a oggetti e interfacce sono uguali e qual è l'errore più comune da parte di un programmatore che finisce per creare quella situazione indesiderata? –
- 1. Alla ricerca di un modo sicuro per distribuire codice PHP
- 2. modo conveniente scrivere interfaccia generica che indica alla sua implementor
- 3. modo migliore per utilizzare un C Interfaccia ++
- 4. Modo corretto per distruggere un modulo e mostrarne un altro in Delphi
- 5. Impedire temporaneamente di estendere la sua durata?
- 6. È sicuro cancellare un oggetto POD con un puntatore alla sua base?
- 7. Come sottrarre due oggetti XmlGregorianCalendar per creare un oggetto Durata?
- 8. Un modo sicuro per archiviare password decifrabili
- 9. Dozer tenta di associare una classe alla sua interfaccia
- 10. Delphi: come creare un TList globale sicuro per thread?
- 11. Oggetti di breve durata
- 12. Cerchi un programmatore di eventi per Delphi?
- 13. Java lanciare un elenco di <object> alla sua interfaccia
- 14. Alla ricerca di un modo per utilizzare un NSArray come presa per un gruppo di pulsanti
- 15. Qual è un buon modo per distribuire un'applicazione Perl?
- 16. Come lanciare un interfaccia a un oggetto in Delphi
- 17. C'è un modo semplice per aggiungere un evento a tutti gli oggetti modulo in C#
- 18. Come stampare un modulo in Delphi?
- 19. È un modo sicuro per impostare il token CSRF?
- 20. Come posso modificare dinamicamente l'altezza della riga di un UIpickerview per tutta la sua durata?
- 21. Delphi, MDI vs Tab per interfaccia multi-documento
- 22. Esiste un modo per un modulo del kernel per trovare gli indirizzi di sezione di un altro modulo caricato?
- 23. C# Il modo migliore per scurire un colore fino alla sua leggibilità
- 24. Distribuire un contenitore finestra mobile alla produzione
- 25. Delphi - modulo nel modulo
- 26. Come creare e liberare in modo sicuro più oggetti in Delphi
- 27. Buone soluzioni per distribuire un Eclipse preconfigurato?
- 28. Un modo semplice per raggruppare gli oggetti in bucket
- 29. C'è un modo in delphi (oggetto Pascal) per creare uno per ciascuno come in java?
- 30. Delphi: Va bene per un modulo liberarlo da solo?
Lebeau, grazie Userò queste informazioni per rivedere il mio codice. –
Perdonate la domanda in ritardo, ma potete indicarmi un buon riferimento che spieghi quando utilizzare TContainedObject anziché TAggregatedObject? Ho guardato l'Aiuto Delphi per un po 'e non riesco a capire le differenze tra maiuscole e minuscole. –