2008-12-14 19 views

Respuesta

6

Esto es solo una opinión, por mi experiencia con lo que las variantes pueden y no pueden hacer.

Si coloca un objeto COM en él, se almacenará como una referencia de IDispatch, y así cualquier llamada de método o propiedades a las que acceda en este objeto se convertirán en algún código que busque el DISPID interno del método/propiedad, se construirá una matriz con argumentos de método, y el método se invocará a través de la interfaz IDispatch.

En otras palabras, IDispatch se maneja para usted, de la forma que normalmente debería hacerlo, pero lo hace automágicamente el compilador.

Sin embargo, para objetos Delphi normales, las cosas se ponen más difíciles. Puede usar RTTI para encontrar y llamar a los métodos y propiedades publicados, pero eso es todo. Si tiene el nombre de un método no publicado y no virtual, Delphi no puede encontrar la dirección correcta para él en su método.

En otras palabras, todo lo que podría hacer sería simplemente mantener el objeto, no podría ser capaz de usarlo. Tal vez podrían agregar soporte para simplemente liberarlo, pero de nuevo, eso probablemente sea.

Sé con certeza que si implementa IDispatch correctamente, puede almacenar de forma segura y utilizar el objeto a través de una variante. Tengo una clase que se puede usar como clase base para los objetos Delphi en los que quieres hacer esto. Expondrá automáticamente los métodos/propiedades publicados, y puede agregar más si lo desea a través de algunas llamadas a métodos protegidos. Si hay interés en dicha clase, puedo ubicarla en algún lugar.

Pero, una vez más, esto es a través de IDispatch, y utiliza los métodos publicados, el resto es código manual, por lo que el soporte para las variantes tiene que ser incorporado en sus objetos por usted.

Por eso creo que acaban de decir: Esto solo generará quejas, que podemos sostener un objeto pero es inútil.

Pero eso es solo mi opinión. Quizás alguien oficial tenga una respuesta mucho mejor.

+4

que está bastante bien. También debe mencionar las clases TCustomVariantType y TInvokeableVariantType. Esas clases muestran todas las cosas que una clase tendría que hacer para poder * usar * (no solo almacenadas) en una Variante, sin implementar necesariamente IDispatch. –

+0

+1 a Rob: TCustomVariantType y TInvokeableVariantType son bastante potentes. Algunas penalizaciones de rendimiento, pero que [se pueden eludir con alguna piratería de bajo nivel] (http://blog.synopse.info/post/2011/07/01/Faster-variant-late-binding). –

24

Definitivamente puede almacenar un objeto dentro de una variable de Variante - simplemente echarlo en un NativeUInt. Un objeto es solo un puntero, de todos modos.

obj := TObject.Create; 
v := NativeUInt(obj); 
obj := TSomeObject(NativeUInt(v)); 
6

que había utilizado variantes para sujetar objetos en el pasado el uso de los componentes internos variante, el código es algo como esto:

var 
    MyObject: TMyObject; 
    Value: Variant; 
begin 
    MyObject:= TMyObject.Create; 
    TVarData(Value).VType:= VarByRef; 
    TVarData(Value).VPointer:= MyObject; 
+1

Tenga en cuenta que está haciendo trampa. VarByRef es una * bandera * destinada a modificar el campo de tipo subyacente. Su código dice que la variable está * vacía *, pero está vacía por referencia. –

+0

Hmmm? Rob, ¿esto significa que varIsEmpty volvería True ??? –

+1

Conceptualmente está bien, creo; lógicamente, una referencia sin tipo a una ubicación es equivalente a un puntero sin tipo, es decir, void * en C o Pointer en Delphi. –

Cuestiones relacionadas