Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > Varios
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Grupo de Teaming del ClubDelphi

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 02-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Como obtener propiedad de una clase que está en una bpl dinámica?

Buenas tardes, a ver si alguien es capaza de resolver este problema...

Tengo una bpl dinámica en la que tengo una clase A.

En mi dpr principal tengo la Clase APADRE de la que hereda la clase A.

Desde mi dpr principal cargo esa Bpl dinámica, como podría acceder a la clase A ó a una de sus propiedades?

No tengo ni idea de como hacerlo pero quería saber si hay algo de tipo:

(ObjetoDeLaClaseAPADRE as A).PropiedadDeLaClaseA

teniendo en cuenta que yo desde mi dpr no veo nada de la bpl dinámica.

Un saludo.
Responder Con Cita
  #2  
Antiguo 02-03-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
En la BPL debes registrar la clase a la que quieres acceder utilizando RegisterClass.

Código Delphi [-]
  RegisterClass(TClaseEnBPL);


Luego para poder acceder a ella desde otro lugar de la aplicación puedes utilizar RTTI. Con el método GetClass puede acceder a la clase a partir de su nombre.

Revisa la ayuda hay algun ejemplo.
También puedes buscar por internet un artículo de "Vino Rodrigues" sobre packages dinámicos. Recuerdo que está muy bien explicado.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #3  
Antiguo 03-03-2007
Avatar de poliburro
[poliburro] poliburro is offline
Miembro Premium
 
Registrado: ago 2004
Ubicación: México D.F
Posts: 3.068
Poder: 23
poliburro Va por buen camino
Este ejemplo carga una clase contenida en un paquete

Código Delphi [-]
 
var
 MHmodfrm : HModule;          
 MTpcfrm : TPersistentClass;  
 Miforma : TFrmBas;        
begin
  MHmodfrm := LoadPackage('rutapaquete');
  clase := GetClass('TClasePErsonalizada');
  Miforma   := TComponentClass(MTpcfrm).Create(Application) As TFrmBas;  
  Miforma.Propiedad := 'Algo'; 
  Miforma.Free;
  UnloadModuleFromInstances(MHmodfrm);
  UnloadPackage(MHmodfrm);
end;


Sencillito pues :P.

si necesitas más detalles, el libro de marco cantú Delphi 7, trae unos excelentes ejemplos.

Suerte
__________________
Conoce mi blog http://www.edgartec.com
Responder Con Cita
  #4  
Antiguo 05-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Muchas gracias por la ayuda, he estado trasteando con ello y viendo ejemplos y más ejemplos pero creo que no lo puedo hacer ya que mi clase hereda de TObject y no de TComponent y al hacer el:

RegisterClass(TClaseEnBPL);

me da error ya que creo que sólo se pueden registrar clases que hereden de TComponent.

Por otro lado al hacer el:

clase := GetClass('TClasePErsonalizada');

siempre me da que clase es nil ya que supongo no llega a registrarse.

Sigo buscando soluciones...gracias.
Responder Con Cita
  #5  
Antiguo 05-03-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por AFilth
...creo que no lo puedo hacer ya que mi clase hereda de TObject y no de TComponent y al hacer el...
El realidad debe derivar de TPersistent, pero no es ningun problema. Puedes cambiar la herencia de tu clase para que en lugar de derivar de TObject, derive de TPersistent (TPersistent deriva a su vez de TObject).
No pierdes nada, al contrario, tal vez estés agregando a tu clase algunas características que no necesita, pero ya está.


Cita:
Empezado por AFilth
...
clase := GetClass('TClasePErsonalizada');
siempre me da que clase es nil ya que supongo no llega a registrarse.
Eso es debido a lo comentado más arriba.
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #6  
Antiguo 05-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Sí, suponía que era por eso, pero la verdad que no me atrevía a cambiar la herencia ya que es una clase muy muy gorda dentro del programa que se usa en muchísimos sitios y me daba cosa, ya que creía que podría tener luego problemas con ella...pero bueno, viendo tu comentario me animaré a hacer la prueba y ya os contaré como ha ido todo.

Muchas gracias y un saludo.
Responder Con Cita
  #7  
Antiguo 05-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Bueno, ahora tengo el siguiente problema:

Tengo la clase A que hereda de TPersistent, y luego la Clase B que hereda de la clase A.

En la unit de la Clase B, en el Inicilization intento hacer un:

RegisterClass(ClaseB);

pero me da el error:

Incompatible types: TagWNDClassA and Class Reference.

Es porque tengo que heredar de otra clase?

Salu2.
Responder Con Cita
  #8  
Antiguo 05-03-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Cita:
Empezado por AFilth
pero me da el error:
Incompatible types: TagWNDClassA and Class Reference.
¿Dónde estás utilizando TagWNDClassA?
¿TagWNDClassA es una clase o una instancia?
Si es una clase, ¿Cómo está definida?
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #9  
Antiguo 05-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Cita:
Empezado por Neftali
¿Dónde estás utilizando TagWNDClassA?
¿TagWNDClassA es una clase o una instancia?
Si es una clase, ¿Cómo está definida?
Hola otra vez, he solucionado ese error...era una tontería. El problema es que en el uses estaba declarado primero Classes y luego Windows por lo que el compilador intentaba hacer el RegisterClass de Windows en lugar del de Classes.

Ya está solucionado cambiando el orden en los uses.
Responder Con Cita
  #10  
Antiguo 05-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Bueno, os sigo contando...

Hemos quedado de esta forma:

Tengo mi bpl dinámica con la ClaseB. En esta unidad en el inicialization hago un:

RegisterClass(ClaseB);

Vale, hasta ahí parece que bien pero luego desde donde quiero acceder a la propiedad de esa ClaseB (Es otra unidad en la cual cargue dinámicamente la bpl de la ClaseB) hago lo siguiente:

Código Delphi [-]
var
  AClass: TPersistentClass;
  FAux: int64;
begin
  AClass := GetClass('ClaseB');
  FAux := GetInt64Prop(ObjetoDeClaseA, 'PropiedadDeClaseB');

Esto me devuelve una excepción de que no ha encontrado esa propiedad. Supongo que es lógico ya que yo le estoy pasando un Objeto que aunque en realidad es de la ClaseB, Delphi lo interpreta como que es de la ClaseA.

Por ello creaía que me bastaría con hacer algo de tipo:
Código Delphi [-]
FAux := GetInt64Prop(ObjetoDeClaseA As AClass, 'PropiedadDeClaseB');

Una especie de cast para que el Delphi supiese que el objeto en realidad es de la ClaseB pero eso no funciona...

De momento vuelvo a estar sin ideas...

Un saludo.
Responder Con Cita
  #11  
Antiguo 06-03-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Cita:
Empezado por AFilth
Supongo que es lógico ya que yo le estoy pasando un Objeto que aunque en realidad es de la ClaseB, Delphi lo interpreta como que es de la ClaseA.
Eso no tendría problema, pero:

El ejemplo que pones es incompleto y no vemos cómo estás construyendo el objeto que le pasas a GetInt64Prop. Fíjate en una cosa: TPersistent no es una clase virtual, esto es, su constructor Create no es virtual. Esto es importante, porque si construyes objetos a partir de referencias de clase- como lo es cuando usas el valor que devuelve GetClass -tal referencia debe apuntar a una clase virtual, de lo contrario, la construcción se resuelve desde el momento de la compilación usándose el constructor base de TPersistent y no el de la clase heredada.

Puedes resolver eso, metiendo un constructor virtual en tu clase A que incluso puedes dejar abstracto e implementarlo hasta la clase B, o bien dejarlo vacío (un procedimiento que no haga nada) y la clase B puede o no redefinirlo.

Pero cuando construyas la clase debes usar una referencia a tu clase A y no a TPersistentClass. Algo como:

Código Delphi [-]
type
  // Tu clase A
  TBaseObject = class(TPersistent)
    constructor Create; virtual; abstract;
  end;

  TBaseClass = class of TBaseObject;

Y usas TBaseClass para hacer un moldeo con el valor que te devuelve GetClass.

Código Delphi [-]
var
  AClass: TBaseClass;

begin
  AClass := TBaseClass(GetClass('TClaseQueDesciendeDeTBaseObject'));
  Base := AClass.Create;

  ...

end;

Como Aclass apunta ahora a una clase virtual, el compilador sabe ya que no puede resolver el constructor y debe dejarlo hasta el momento de la ejecución.

Otra cosa, es que no veo cómo estás definiendo la clase en cuestión: recuerda que las propiedades a las que quieres acceder deben estar en una sección published.

Además, en mi opinión, no hay necesidad de usar TPersistent. TPersistent y TComponent son las clases bases para el manejo de la persistencia en los archivos dfm. Si tú no requieres tal funcionalidad, no veo porqué usarlo.

Cualquier clase puede generar RTTI siempre y cuando se compile con la directiva {$M+}. Como TPersistent está compilado de esa forma, ella, y todas las classes descendientes, generan RTTI. Pero puedes lograr lo mismo si lo haces tú mismo:

Código Delphi [-]
type
  {$M+}
  type
    TBaseObject = class
      constructor Create; virtual; abstract;
    end;
  {$M-}

Claro que en esta situación no te va a servir GetClass. Pero GetClass y RegisterClass lo único que hacen es mantener una asociación:

nombre de clase => clase

que tú mismo puedes implementar fácilmente.


Y finalmente, de hecho no entiendo para qué quieres usar RTTI. Hasta donde recuerdo, tu puedes tener una unidad común, digamos Core que defina tu clase base, si quieres con sólo métodos abstractos para que haga lo mínimo indispensable. Entonces, incluyes esa unidad Core, tanto en la aplicación principal como en el paquete dinámico.

Dado que en Core estás definiendo la interfaz de tu clase, puedes acceder a los métodos y propiedades sin recurrir a las argucias de RTTI. Claro está, siempre y cuando te bases en una clase virtual, según te comenté arriba.

Eso sí, tienes que implementar tu propio registro

nombre de clase => clase

pero eso es relativamente sencillo. Puedes tener en Core un arreglo

Código Delphi [-]
var
  RegisteredClasses: array of TBaseClass;

y funciones globales:

Código Delphi [-]
RegisterBaseClass(Nombre: String; AClass: TBaseClass);
function GetBaseClass(Nombre: String): TBaseClass;

// Saludos

Última edición por roman fecha: 06-03-2007 a las 06:31:55.
Responder Con Cita
  #12  
Antiguo 07-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Muchas gracias por tu extenso comentario Roman, me ha despejado muchas dudas que tenía.

Al final os cuento como solucioné e tema para que quede constancia por si algún día alguien busca algo parecido.

Uno de mis problemas era que la propiedad de la ClaseB la tenía definida en Public en vez de en Published por lo que no tenía acceso a ella desde la RTTI.

Por otro lado no sabía lo de la directiva de compilación {$M+} por lo que al final hice que la ClaseA heredase de TPersistent aunque ésto lo podría cambiar ahora volviendo a la herencia de TObject y compilando con la directiva que nos ha comentado Roman.

Al final no necesite para nada el GetClass, ya que lo único que tenía que hacer era escribir en una de las propiedades de la ClaseB por lo que desde el exterior me basto con hacer un:
Código Delphi [-]
SetObjectProp(MiObjeto, 'Propiedad', Valor);

Un saludo y una vez más gracias a todos por vuestra ayuda.
Responder Con Cita
  #13  
Antiguo 07-03-2007
Avatar de roman
roman roman is offline
Moderador
 
Registrado: may 2003
Ubicación: Ciudad de México
Posts: 20.269
Poder: 10
roman Es un diamante en brutoroman Es un diamante en brutoroman Es un diamante en bruto
Hola AFilth,

Me gustaría que me explicases una cosa. Si no usas GetClass para nada, ¿cómo estás obteniendo MiObjeto? ¿De dónde sale? Tiene que haberse instanciado en algún momento, ¿cómo?

// Saludos
Responder Con Cita
  #14  
Antiguo 07-03-2007
Avatar de Neftali [Germán.Estévez]
Neftali [Germán.Estévez] Neftali [Germán.Estévez] is offline
[becario]
 
Registrado: jul 2004
Ubicación: Barcelona - España
Posts: 18.233
Poder: 10
Neftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en brutoNeftali [Germán.Estévez] Es un diamante en bruto
Yo también me apunto a eso.
¿Cómo has obtenido la referencia de la clase que hay en el package dinámico?
__________________
Germán Estévez => Web/Blog
Guía de estilo, Guía alternativa
Utiliza TAG's en tus mensajes.
Contactar con el Clubdelphi

P.D: Más tiempo dedicado a la pregunta=Mejores respuestas.
Responder Con Cita
  #15  
Antiguo 07-03-2007
AFilth AFilth is offline
Miembro
 
Registrado: ago 2005
Posts: 119
Poder: 19
AFilth Va por buen camino
Vamos alla con la explicación, lo intentaré lo mejor que pueda aunque es algo que no he implementado yo y lo mismo meto la pata por algún lado...

Por una lado tengo mi proyecto principal, desde donde hago el
Código Delphi [-]
SetObjectProp(MiObjeto, 'Propiedad', Valor);

Por otro lado tengo una bpl en la que está la ClaseA, esta bpl no se carga dinámicamente.

Y finalmente tengo otra bpl que se carga dinámicamente con la ClaseB, esta clase hereda de la ClaseA, ya que en su uses hace referencia a las units de la bpl donde está contenida la ClaseA.

Normalmente en la aplicación se cargan objetos de la ClaseA, pero cuando se cumplen una serie de condiciones, se carga la BPL donde está contenida la ClaseB y en vez de crearse los objetos de ClaseA se crean de ClaseB.

Bueno, ahora empieza lo difícil, a ver si soy capaz de explicarlo bien...

En mi bpl donde está contenida la ClaseA se hace lo siguiente:
Código Delphi [-]
PClaseA= class of ClaseA;
VAR
TClaseN: PClaseA;

y luego:
Código Delphi [-]
initialization
  TClaseN := ClaseA;

La bpl donde está contenida la Clase B (la que era dinámica) hace:

Código Delphi [-]
PClaseB= class of ClaseA;
VAR
TClaseN: PClaseB;

y luego:
Código Delphi [-]
initialization
  TClaseN := ClaseB;

Luego en todos los Creates y demás métodos, como son override lo que se usa es El TClaseN.Create. Así se consiguen crear objetos de una clase o de otra dependiendo de las circunstancias.

Por lo tanto cuando yo, desde mi proyecto principal hago referencia a un objeto, éste puede ser en realidad de ClaseA ó de ClaseB dependiendo de si se cargo la bpl dinámica ó no.

Espero haberme explicado más o menos con claridad, aunque no sé yo porque ni yo mismo lo entiendo demasiado bien...

Un saludo.
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Usar una clase que esta dentro de una libreria lookmydoom OOP 3 18-04-2006 16:25:34
Obtener el directorio donde está el ejecutable daly Varios 3 13-10-2005 20:29:18
Propiedad que me indica si un DBMemo está vacio gluglu Varios 4 10-02-2005 17:48:17
Una clase como propiedad de un componente? setry2 OOP 3 30-12-2003 22:30:58
Obtener la clase de objetos Feñiz OOP 7 08-05-2003 21:21:55


La franja horaria es GMT +2. Ahora son las 23:22:07.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi