Aufruf einer (Klasse-)Methode nur anhand des Namens



  • -Ich rufe normalerweise Funktionen immer mit Namen auf?

    Hm, ich habe mein Problem nicht genau genug beschrieben.
    Am besten ich versuche es mit einem Beispiel:

    In einer Schleife gehe ich alle Komponenten eines Formulars durch.
    Ich weiß nun von einer Komponente, daß sie die Methode "Show()" be-
    sitzt, kenne aber den Typ zur Design-Zeit nicht, d.h. ich kann keinen
    cast auf einen bestimmten (Klassen-)Typ machen und TComponent hat
    keine Methode Show(). Was ich suche ist eine Funktion, der ich ein
    Objekt übergebe, einen Methodennamen und u.U. noch eine Argumentenliste,
    und die dann versucht, diese Methode auf dem Objekt aufzurufen, also
    etwa in dieser Form:

    CallByName(TObject*, char*, void*)
    

    oder so ähnlich. Gibt es so eine Funktion?

    Gruß,

    Alexander Kempf



  • Ah jetzt... KlausB hat recht in der FAQ gibts im Abschnitt "komponenten" was dazu "Zugriff aber nicht durch Namen"...

    -junix



  • KlausB schrieb:

    schau mal in die FAQ
    da ist es sehr gut beschrieben

    Kannst Du mir sagen wo? Ich finde es nicht. Vielleicht suche ich an
    der falschen Stelle...

    Gruß,

    Alexander Kempf



  • junix schrieb:

    Ah jetzt... KlausB hat recht in der FAQ gibts im Abschnitt "komponenten" was dazu "Zugriff aber nicht durch Namen"...

    Den Eintrag hatte ich schon gesehen, aber das löst mein Problem nicht.
    Hier ist mal ein Ausschnitt aus meinem Code:

    TForm* form;
    //ein paar Zeilen ausgelassen
    TMetaClass* mc;
    for (int i=0; i<form->ComponentCount; ++i)
    {
       mc = form->Components[i]->ClassType();
       while (!mc->ClassNameIs("TComponent") && !mc->ClassNameIs("TControl"))
          mc = mc->ClassParent();
       if (mc->ClassNameIs("TControl"))
       {
          // Einfach mal nach TButton konvertieren...
          // ... ist aber Schweinerei!
          ((TButton*) form->Components[i])->OnMouseMove = &FormMouseMove;
          // FormMouseMove ist irgendwo anders definiert
       }
    }
    

    Der obige Code funktioniert, aber einfach mal aus Spaß auf TButton casten,
    ist irgendwie nicht so sauber. Hier ist es natürlich auch eine Eigenschaft,
    aber mit Methoden hat man das gleiche Problem.

    Gruß,

    Alexander Kempf



  • Entweder du fragst nach ClassNameIs("TButton") dann kannst du einfach mal drauf los casten oder du verwendest dynamic_cast. (Belies dich dazu ebenfalls in der FAQ) der C-Style-Cast sollte eigentlich seit C++ nichtmehr verwendet werden...

    -junix



  • junix schrieb:

    Entweder du fragst nach ClassNameIs("TButton") dann kannst du einfach mal drauf los casten oder du verwendest dynamic_cast. (Belies dich dazu ebenfalls in der FAQ) der C-Style-Cast sollte eigentlich seit C++ nichtmehr verwendet werden...

    -junix

    In dem Beispiel kann ich keinen dynamic_cast verwenden, sonst funktioniert's
    nur für TButton, was ja auch eigentlich sehr sinnvoll ist. Mein Problem ist,
    daß ein Formular ja normalerweise nicht nur aus Buttons besteht;)
    Es wird sehr viele Controls unterschiedlicher Typen besitzen, die aber alle
    von TControl erben und deswegen potentiell eine Eigenschaft OnMouseMove be-
    sitzen könnten.
    Natürlich kann ich in einer riesigen if-else-if-Kette versuchen alle Typen
    abzuprüfen. Aber was, wenn ein Control auf dem Formular ist, das nicht in
    meiner Liste ist? Mit meinem C-Style-Cast auf TButton funktioniert das, weil
    es keinerlei Typsicherheit bietet, aber es ist nicht gerade schön.

    Gruß,

    Alexander Kempf



  • vielleicht sagst du auch mal, was genau du erreichen willst, eventuell gibt es ja einen anderen lösungsweg zu deinem problem...



  • Du könntest auch von allen Komponenten neue Ableiten, die dann mit Hilfe von ActiveX und Typelibraries, auch ihr Methoden als String preisgeben würden.



  • Jede Klasse könnte eine Map mit dem String als Schlüssel und eine Methodenzeiger als Wert besitzen.



  • Würde sowas funktionieren ?

    class TNewControl: public TControl
    {
    public:
       __property OnMouseMove;
    };
    
    ...
       // Einfach mal nach TButton konvertieren...
       // ... ist aber Schweinerei!
       TNewControl *ctrl = dynamic_cast<TNewControl*>(form->Components);
       if (ctrl)
          ctrl->OnMouseMove = &FormMouseMove;
    ...
    


  • bIce schrieb:

    Du könntest auch von allen Komponenten neue Ableiten, die dann mit Hilfe von ActiveX und Typelibraries, auch ihr Methoden als String preisgeben würden.

    kommt mir sehr aufwendig vor und ich kenne u.U. auch nicht alle Komponenten
    im Vorfeld. Dann wird's mit dem Ableiten schwierig...



  • Anonymous schrieb:

    Jede Klasse könnte eine Map mit dem String als Schlüssel und eine Methodenzeiger als Wert besitzen.

    Kann ich das z.B. bei TButton o.ä. selbst beeinflussen?
    Ich glaube, das habe ich nicht ganz verstanden.



  • bIce schrieb:

    Würde sowas funktionieren ?

    class TNewControl: public TControl
    {
    public:
       __property OnMouseMove;
    };
    
    ...
       // Einfach mal nach TButton konvertieren...
       // ... ist aber Schweinerei!
       TNewControl *ctrl = dynamic_cast<TNewControl*>(form->Components);
       if (ctrl)
          ctrl->OnMouseMove = &FormMouseMove;
    ...
    

    Wegen des dynamic_cast dürfte sowas nicht funktionieren (oder?). Lasse ich
    den dynamic_cast weg, habe ich das gleiche wie vorher, nur mit einer selbst-
    geschriebenen Klasse anstatt TButton. (Oder liege ich völlig falsch?)



  • Sunday schrieb:

    vielleicht sagst du auch mal, was genau du erreichen willst, eventuell gibt es ja einen anderen lösungsweg zu deinem problem...

    Also, ich möchte eine Komponente erstellen, die immer, wenn ein Formular in
    der Anwendung geladen wird, dieses Formular übersetzt. D.h. ich gehe alle
    Komponenten auf dem Formular durch und setze Caption, Text oder auch andere
    Eigenschaften. Welche Eigenschaften eine solche Komponente hat, kann ich
    dabei nicht vorher wissen: Es können ja auch Komponenten von Dritt-Her-
    stellern sein.
    Deshalb möchte ich zur Laufzeit herausfinden, welche Eigenschaften eine
    Komponente hat und möchte auch den Wert ändern können.
    Ist mein Problem jetzt etwas besser verständlich?



  • Alexander Kempf schrieb:

    Welche Eigenschaften eine solche Komponente hat, kann ich dabei nicht vorher wissen: Es können ja auch Komponenten von Dritt-Herstellern sein.

    Wenn du nicht weisst, um was für Komponenten es sich handelt, woher willst du denn dann wissen, was du da eigentlich reinschreiben sollst?



  • Du kannst anstelle nach TButton auch nach einem gemeinsamen Vorfahren casten(natürlich mit dynamic_cast), der die gewünschte Eigenschaft oder Methode hat, um die Anzahl der Fälle zu reduzieren. Dazu zeigt dir die Hilfe die Objekthierarchie an.



  • Geo:
    Damit (StichWort InheritsFrom()) kann man den Umfang der Abfragen zwar reduzieren, am "Problem" des if/else-Konstukts ändert sich aber nichts. Und wenn eine (3rd-party)Komponente von einer in der Hierarchie hochstehenden Klasse wie zB. TWinControl direkt abgeleitet wurde nützt dir das ja auch nicht wirklich etwas.



  • Jansen schrieb:

    Alexander Kempf schrieb:

    Welche Eigenschaften eine solche Komponente hat, kann ich dabei nicht vorher wissen: Es können ja auch Komponenten von Dritt-Herstellern sein.

    Wenn du nicht weisst, um was für Komponenten es sich handelt, woher willst du denn dann wissen, was du da eigentlich reinschreiben sollst?

    Ich stelle mir das so vor, daß die Informationen z.B. aus einer XML-Datei
    oder aus einer Datenbank kommen. Wie die Daten da reinkommen ist ein anderes
    Thema, aber auch dafür habe ich schon (noch nicht ganz konkrete) Vorstellungen.
    Es gibt ja aber auf jeden Fall für visuelle Komponenten Eigenschaften die mit
    großer Wahrscheinlichkeit wirklich existieren, wie "Caption" oder "Text". Die
    könnte man dann mal "auf Verdacht" setzen und das ganze in einen try/catch-
    Block setzen.
    Schwierig, schwierig...



  • Jansen schrieb:

    Geo:
    Damit (StichWort InheritsFrom()) kann man den Umfang der Abfragen zwar reduzieren, am "Problem" des if/else-Konstukts ändert sich aber nichts. Und wenn eine (3rd-party)Komponente von einer in der Hierarchie hochstehenden Klasse wie zB. TWinControl direkt abgeleitet wurde nützt dir das ja auch nicht wirklich etwas.

    Genau.
    Ich glaube, hier hat mich jemand verstanden 😉 Ganz schön schwer, was zu er-
    klären, so daß es alle verstehen.


Anmelden zum Antworten