Tengo un formulario de Delphi que proporciona la funcionalidad detrás de un objeto de interfaz que otras partes del código obtienen referencias también a través de una propiedad que pertenece al formulario. No puedo delegar la funcionalidad de la interfaz a un objeto secundario porque los controles/componentes en el formulario tienen demasiada funcionalidad. No puedo usar TAggregatedObject o TContainedObject para vincular el tiempo de vida de los objetos interconectados que se pasan al formulario porque la clase TForm no hereda de TinterfacedObject y Delphi no admite herencia múltiple, por lo que no puedo mezclar en TInterfacedObject en la cadena de herencia. . Esta situación puede provocar violaciones de acceso si un formulario se destruye mientras que otro código contiene una de las referencias de interfaz que el formulario expidió. ¿Alguien puede pensar en una buena solución a este problema?¿Manera segura en Delphi para un formulario para distribuir objetos de interfaz vinculados a su tiempo de vida?
Respuesta
Puede delegar la interfaz a un objeto secundario, simplemente haga que ese objeto contenga un puntero interno al formulario para que pueda acceder a los controles del formulario cuando sea necesario, no diferente de lo que ya está haciendo en este momento.
Puede usar TAggregateObject
o TContainedObject
para sus necesidades. No requieren que el formulario derive de TInterfacedObject
. Lo único que hacen es requerir un puntero de interfaz de IInterface
, y TComponent
deriva de IInterface
(y anula la _AddRef()
y _Release()
desactivar la cuenta de referencias), por lo que puede pasar el propio formulario (por ser un descendiente TComponent
) como el puntero IInterface
requerido.
Eso deja el único problema restante: el cierre del Formulario mientras las referencias de la interfaz activa están siendo retenidas por otro código. La solución más simple es: 1) reescribir ese código para no mantener esas referencias mientras el Formulario se está cerrando, o 2) no permitir que el Formulario se cierre hasta que esas referencias hayan sido liberadas.
Nota: Esto solo funcionará, si su consumidor también se deriva de TComponent.
Para evitar las referencias muertas puede consultar la IInterfaceComponentReference
(disponible en todos los TComponent) de su formulario, llame GetComponent
en esa interfaz y apegarse a la FreeNotification
del Componente/Formulario devuelto.
Lo que sucede ahora es: cuando la forma se destruye se notificará a todos los "listners" que su va a destruirse a sí misma llamando al método Notification
en el consumidor con ella misma (forma) como AComponent
y opRemove
como la operación. De este modo, te permite anular la referencia de tu interfaz. Pero tenga en cuenta que las referencias de objeto y las referencias de interfaz no deben ser iguales. También asegúrese de llamar al RemoveFreeNotification
cuando ya no necesite la Notificación para evitar llamadas innecesarias.
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;
¡Agradable! No sabía sobre eso. ¿Podría ampliar un poco su declaración: "pero tenga en cuenta que las referencias de los objetos y las referencias de interfaz no deben ser iguales"? –
Bueno, varias razones: a) puede hacer una implementación personalizada de 'QueryInterface' que puede devolver un nuevo objeto interconectado en cada llamada. b) En segundo lugar, puede delegar la interfaz a una propiedad (Win32), lo que podría volver a crear un nuevo objeto cada vez. c) La implementación de 'TObject.GetInterface' agrega un interfaceOffset a la dirección.(Pero estos elementos internos están desafortunadamente más allá del conocimiento de mayo) La interfaz recientemente introducida (Delphi 2010) para la fundición de objetos se realiza básicamente mediante la consulta de una interfaz de marcador que devuelve la dirección de entrada del objeto. –
¿Qué pasará si el objeto y las referencias de la interfaz son iguales y cuál es el error más común cometido por un programador que termina creando esa situación no deseada? –
- 1. Objetos vinculados a salmuera
- 2. manera segura (st) cambiar el nombre de un proyecto delphi
- 3. Manera segura para almacenar dos tipos de objetos en una colección
- 4. ¿La conexión TADOConnection de Delphi es segura para subprocesos?
- 5. Java: Imposición de objetos doblemente vinculados
- 6. Objetos de vida corta
- 7. Struct vs Class para objetos de larga vida
- 8. ¿Cómo puedo obtener Delphi 2010 IDE para mostrar una vista dividida con un formulario y su código al mismo tiempo?
- 9. distribuir la opción en el constructor de interfaz de iPhone
- 10. Opciones para identificar objetos de manera única en el tiempo de ejecución?
- 11. ¿Buenas soluciones para distribuir un Eclipse preconfigurado?
- 12. manera genérica para reemplazar un objeto en su propio método
- 13. Matemáticas de tiempo en Delphi
- 14. Delphi: transporte de objetos a computadoras remotas
- 15. ¿Cómo acceder a un control de formulario para otro formulario?
- 16. ¿Busca un programador de eventos para Delphi?
- 17. ¿Hay una implementación de grupo de objetos C++ segura y segura para subprocesos?
- 18. Fecha de creación automática para objetos de formulario modelo django?
- 19. Almacenamiento de objetos en iOS para su uso posterior
- 20. Auto Suspendiendo un hilo en Delphi cuando no es necesario y reanudando de manera segura
- 21. Uso de asignaciones dinámicas en un software crítico para la vida o crítico para la vida
- 22. Asignación eficiente de muchos objetos pequeños de vida corta
- 23. Vida útil de objetos Qt
- 24. Delphi - formulario dentro del formulario
- 25. ¿Hay alguna biblioteca PRNG criptográficamente segura para Delphi?
- 26. punteros que regresan de una manera segura para los subprocesos
- 27. Qt para desarrolladores Delphi
- 28. Vida útil de los objetos temporales en C11 vs C99
- 29. ¿Cómo se traducen los datos en un objeto FileReader a datos de formulario para su carga?
- 30. C objetos en tiempo de ejecución, límites dll
Lebeau, gracias Voy a utilizar esa información para revisar mi código. –
Perdón por la última pregunta, pero ¿puede indicarme una buena referencia que explique cuándo utilizar TContainedObject en lugar de TAggregatedObject? He mirado fijamente la Ayuda de Delphi por un tiempo y realmente no puedo aclarar las diferencias de casos de uso. –