Ir al contenido


Foto

Crear objeto sabiendo el nombre de la clase


  • Por favor identifícate para responder
7 respuestas en este tema

#1 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 septiembre 2010 - 12:13

Buenas,

No se si se me está yendo la olla o qué pero..... sabiendo el nombre de una clase (en una variable tipo string), cómo crear un objeto de dicha clase? He probado con GetClass, pero no se si es la manera correcta



delphi
  1. var
  2.   AClass: TPersistentClass;
  3.   AFrame: TCustomFrame;
  4. begin
  5.   AClass := GetClass('TConfig');
  6.  
  7.   if AClass <> nil then
  8.   begin
  9.     AFrame := TComponentClass(AClass).Create(Application) as TCustomFrame;
  10. .....



Gracias

Nos leemos

  • 0

#2 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 septiembre 2010 - 01:02

Hola Cadetill,

Pues no veo otro modo de hacerlo. Ahora el asunto es si eso es sólo un ejemplo o si realmente haces uso de clases y objetos que derivan de TPersistent.

El asunto es que GetClass sólo funciona para aquellas clases que forman el conjunto de persistentes.

Si no es tu caso (es decir tienes tus propias clases que no derivan de TPersistent) no veo otro modo que optar por un sistema basado en factoría y disponer de tu propia referencia de clases y tener tus clases "registradas" en una clase *List. Como el que menciona Roman:
http://www.clubdelph...ead.php?t=17623

Y si usas D2007 o superior, quizá esto te interese:
http://www.clubdelph...ad.php?p=253999

EDITO:
Si es necesario te preparo un ejemplo simple.

Saludos,
  • 0

#3 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 18 septiembre 2010 - 02:15

Saludos.

Para que GetClass funcione adecuadamente debes primero de registrar la clase. En otras palabras debes de usar RegisterClass; siempre utilizo dicho método en el Initialization de la unidad y UnregisterClass en el Finalization.

Registers a class of persistent object so that it’s class type can be retrieved.
Call RegisterClass to register a class with the streaming system. Form classes and component classes that are referenced in a form declaration (instance variables) are automatically registered.  Any other classes used by an application must be explicitly registered by calling RegisterClass if instances are to be saved.

Once classes are registered, they can be loaded or saved by the component streaming system. IdentToInt returns nil (Delphi) or NULL (C++) when passed the class name of an unregistered class, and FindClass raises an exception for unregistered classes.

The AClass parameter is the class that is descended from TPersistent. Put the call to RegisterClass in a Register procedure. In Delphi, you can also put the call in the initialization section of the unit in which the class is defined. In C++, the call can also go in the namespace of the compilation unit that defines the class.

If the class is already registered, RegisterClass does nothing. If a different class with the same name is already registered, RegisterClass raises an EFilerError exception.

Note:    Registering a component using the RegisterNoIcon or RegisterComponents method does not automatically register the class. It is still necessary to call RegisterClass for components.


Espero te pueda servir! (y)
  • 0

#4 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 septiembre 2010 - 03:39

Muy cierto Rolphy,
Hay que registrar la clase.

De todas formas, el uso de GetClass solo servirá si las clases a utilizar pertenecen a la rama de herencia del TPersistent.

Si Cadetill desea hacer uso de clases que no pertenecen a esa rama ya no es posible esa técnica y debe recurrirse a factorías o fábricas.

Saludos,
  • 0

#5 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 18 septiembre 2010 - 03:49

Buenas,

Gracias por contestar a ambos.

Con lo que respecta al tema del registro de las clases, dado que son clases que están en el mismo proyecto imagino que se registran y desregistran automáticamente, ¿no?

No obstante, explico un poco lo que pretendo hacer. Estoy realizando una aplicación que llegará a ser una aplicación de gestión y control de estocs. El cliente quiere que la aplicación tenga unos determinados warnings, es decir, cuando suceda X cosa, le aparezca un aviso.

Los avisos serán todos iguales, sólo cambiará la imagen a mostrar (archivo de recursos) y texto explicativo (tabla de avisos en la base de datos).

He creado un TFrame (TWarningFrm) base que hace todo el trabajo. Las clases descendientes de este TFrame lo único que hacen es, según el tipo de aviso (definido en la tabla de la base de datos) cargar una u otra imagen del fichero de recursos.

Como quiero hacer algo un poco genérico para no tener que tocar mucho código si el cliente decide añadir/quitar avisos, lo que hago es crear los TFrame en tiempo de ejecución, pero claro, no puedo crear TWarningFrm a pelo, tengo que crear sus hijos.

Podría tener un case con los diferentes tipos



delphi
  1. while not tablaAvisos.Eof do
  2. begin
  3.   case tablaAvisosTIPOAVISO.AsInteger do
  4.     1: Frm := TTipoFrm1.Create(Self);
  5.     2: Frm := TTipoFrm2.Create(Self);
  6.     .....
  7.   end;
  8.  
  9.   ......
  10. end;



Pero no me convence la idea porque el case podría crecer y crecer y crecer.... quedando poco bonito el código.

Así que la otra idea que se me ha pasado por la cabeza es tener un campo en la tabla de la base de datos que se diga ClaseFrame de tipo varchar y que contenga "TTipoFrm1", "TTipoFrm2",.....

Así en el bucle que recorre la tabla sólo tenga que hacer el Create de la clase que toque

Nos leemos y gracias por los comentarios

PD: también había pensado crear los avisos como un sistema de pluggins, ¿qué os parece?

  • 0

#6 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 18 septiembre 2010 - 04:32

Hola Cadetill,

Leyendo lo que describes, no veo necesidad de crear frames basados en otro. A menos que dicho frames tenga alguna funcionalidad/características que difiera de uno a otro.

Yo sólo veo un solo Frame en el que se le asocia una imagen y un texto. En vez de crear tipos de Frame, yo entiendo que existe un TFrameAviso con un método CargarImagen() y CargarTexto() hipotético, o de forma más simple, con un



delphi
  1. procedure TFrameAviso.CargarInfoDeAviso(Tipo Aviso: TipoAviso);



Este CargarInfoDeAviso recibiese como parámetro el tipo de aviso, de un tipo indicado. Puede ser string, numérico, el que gustes.

De ese modo cuando se Invoque a CargarInfoAviso() se le pasa el tipo.

Este CargarInfoAviso() buscará en la tabla el aviso en cuestión y sabrá que texto e imagen tener.

No veo el porqué molestarse con varios Frames, directamente uno sólo cuyo texto e imagen se cambie según algún parámetro que se reciba.

¿Me explico?

Yo me imagino una tabla algo así:

Tabla: TipoAviso
IDAviso (PK)
NombreAviso
NombreImagen
Texto

De modo que cuando se cree el frame (o cuando se visualize) que se haga la consulta, se lean el campo NombreImagen y Texto y se los ponga al frame.

Algo simple.... como:



delphi
  1. procedure TFrameAviso.CargarInfoDeAviso(Aviso: string);
  2. var img, texto: string;
  3. begin
  4.   Consulta.SQL := 'select NombreImagen, Texto from TipoAviso where NombreAviso = ' + Aviso;
  5.   Consulta.Open;
  6.  
  7.   img := Consulta.FieldByName(NombreImagen).AsString;
  8.   texto := Consulta.FieldByName(NombreImagen).AsString;
  9.  
  10.   CargarImagen(img);
  11.   CargarTexto(texto);
  12. end;



De ese modo un CargarTexto podría ser algo como:



delphi
  1. procedure TFrameAviso.CargarTexto(Texto: string);
  2. begin
  3.   TFrameLabelTexto.Caption := Texto;
  4. end;



Ves... simple... no existen frames. Es uno solo... la información se extrae desde sea necesario y con ello en mano se altera el contenido del frame.

Es un ejemplo burdo, está sujeto a mejoras.

Ahora bien, si cada Frame cuenta con funcionalidades extras, y cuyo comportamiento varía de hermano a hermano, entonces si veo muy factible y necesaria la posibilidad de una Factoría. En tu caso, como se trata de la posibilidad que crezca a demanda, se necesita de la fábrica basada en *List (TList, TObjectList, TStringList, o cualquier otro "List") ya que éstos te permitirían añadir, modificar y eliminar tantos frames como gustes.

Sobre la posibilidad plugins, ya no te sabría decir.

Saludos,
  • 0

#7 cadetill

cadetill

    Advanced Member

  • Moderadores
  • PipPipPip
  • 994 mensajes
  • LocationEspaña

Escrito 20 septiembre 2010 - 02:56

Buenas,

Bueno, sí, podría mirar de poner en la base de datos la especialización (las imágenes y el texto) y así no tener que hacer herencia. Luego, si se complicase la cosa con nuevos requerimientos, pues ya haría la fábrica de clases.

Así me evito la herencia, no lo había pensado así. Si ya digo yo que a veces cuatro ojos ven más que dos :D

Gracias

Nos leemos

  • 0

#8 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 20 septiembre 2010 - 07:26

No hay problema amigo, ya sabes aquí estaremos para asistirte.  :)

Solo una cosa, no tengo 2 ojos... verás amigo, soy un tanto peculiar: gozo de la capacidad de generar personalidades.... y al día de hoy convivimos 5 así que habemos 12 ojos mirando el problema. :D
No te asustes, si la banda DA pudo aguantarme estos años, tu también podrás soportar al grupito Delphius.  :D :D :D

Saludos,
  • 0




IP.Board spam blocked by CleanTalk.