xe2 versiones que para full ex8 embarcadero creadores delphi interface ide delphi-2007 design-time

delphi - versiones - Error de propiedades de la interfaz publicada y soluciones



que es delphi 2010 (1)

Escribí un conjunto de componentes que se vinculan entre sí a través de propiedades de interfaz publicadas. Están registrados e instalados en un paquete de diseño.

El uso de propiedades de interfaz publicadas no es tan común en Delphi, y por lo tanto, como era de esperar, no parece funcionar tan bien.

Funciona bien cuando los componentes residen en el mismo formulario, sin embargo, los enlaces de propiedad de la interfaz entre los componentes en diferentes formularios causan problemas.

A diferencia de los enlaces de objeto a componentes en otro formulario, IDE no parece reconocer los enlaces de interfaz. Lo que quiero decir se describe mejor con un ejemplo, cuando tiene 2 formularios abiertos en IDE y tiene enlaces entre componentes, entonces tratar de cambiar a la vista de formulario como texto (Alt + F12) haría que IDE se queje correctamente de que:

Module ''UnitXXX.pas'' has open descendents or linked modules. Cannot close.

Pero si la propiedad es una interfaz, entonces esto no sucede, lo que sucede es que el enlace se corta (y ese es el mejor de los casos cuando se usa el mecanismo de Notificación para borrar referencias, de lo contrario, se queda con un puntero no válido)

Otro problema, probablemente como consecuencia del mismo error, es que cuando abre un proyecto en IDE, el orden en que se volverán a abrir los formularios no está definido, por lo que IDE puede intentar abrir un formulario que contenga componentes que tengan enlaces de interfaz a los componentes otra forma, pero esa otra forma no se recrea aún. Por lo tanto, esto resulta efectivamente en enlaces AV o cortados.

En los años 90, mientras usaba Datasets y Datasources , recuerdo problemas similares con la desaparición de los enlaces entre formularios, por lo que esto es algo similar.

Como una solución temporal añadí propiedades publicadas duplicadas, para cada propiedad de la interfaz agregué otra que se declara como TComponent . Esto hace que Delphi sepa que existe un vínculo entre formularios, pero es una solución fea por decir lo menos.

Entonces, me pregunto si hay algo que pueda hacer para solucionar este problema. Es un error IDE y probablemente no se puede reparar directamente, pero tal vez pueda anular algo o engancharme al mecanismo de transmisión para solucionar este error de manera más efectiva.

No he profundizado tanto en el mecanismo de transmisión, pero sospecho que se supone que el mecanismo de reparación se ocupa de esto. Hay un csFixups TComponentState así que espero que haya una solución alternativa.

Editar: Usando D2007 .

Actualizar:

Nuevo ejemplo reproducible actualizado subido a http://www.filedropper.com/fixupbugproject2

Se agregó la property ComponentReference: TComponent para que sea fácil comparar y rastrear la interfaz frente a la transmisión de componentes.

Reduje el problema al nivel de ensamblador, que está un poco fuera de mi alcance.

En el procedimiento GlobalFixupReferences en la unidad de classes llama:

(GetOrdProp(FInstance, FPropInfo) <> 0)

que eventualmente ejecuta:

function TInterfacedComponent.GetInterfaceReference: IInterface; begin // uncomment the code bellow to avoid exception { if (csLoading in ComponentState) and (FInterfaceReference = nil) then // leave result unassigned to avoid exception else } result := FInterfaceReference; // <----- Exception happens here end;

Como puede ver en el comentario, la única forma que encontré para evitar la excepción es dejar el resultado sin asignar, pero eso rompe la funcionalidad ya que la comparación anterior en GlobalFixupReferences falla debido a GetOrdProp <> 0 , que corta el vínculo.

rastreando más profundo, la ubicación más exacta de la excepción está en

procedure _IntfCopy(var Dest: IInterface; const Source: IInterface); en la unidad del system

Esta línea en particular levanta una read of address 0x80000000

{ Now we''re into the less common cases. } @@NilSource: MOV ECX, [EAX] // get current value

Entonces, por qué MOV falla y qué pasa con ECX o EAX no tengo ni idea.


Para resumir, el problema ocurre solo con las propiedades de interfaz publicadas que tienen un método getter, y la propiedad apunta al componente en otro formulario / módulo (y ese formulario / módulo aún no se recrea). En tal caso, la restauración del formulario DFM causa un AV.

Estoy bastante seguro de que el error está en el código ASM en GetOrdProp , pero está más allá de mi capacidad de corrección, por lo que la solución más fácil es utilizar un campo en lugar de un método getter y leerlo directamente en la propiedad. Esto es, afortunadamente, lo suficientemente bueno para mi caso actualmente.

Alternativamente, puede declarar la propiedad como TComponent lugar de la interfaz, luego escribir un descendiente TComponentProperty , anular ComponentMayBeSetTo para filtrar el componente que no admite la interfaz requerida. Y, por supuesto, registrarlo usando RegisterPropertyEditor