Class Routing



  • Moin ­čśë

    In meinem Web-Application Framework wird nach Klassen geroutet. In der Routingtable ist daf├╝r zu jedem URL ein Klassenname angegeben. Mit diesem Namen wird das ResponseObjekt erstellt wie folgt:

    $bin = readbinf(BINFILE); // Routingtable
    $class = isset($bin[$url]['class']) ? $bin[$url]['class'] : 'NotFound';
    require_once "$class.php"; 
    $BODY = ob_get_clean(); ob_start(); # Klassendatei kann HTML enthalten
    $ro = new $class (array('BODY' => $BODY, 'BIN' => $bin, 'URL' => $url, 'SESSION' => $SESSION));
    
    

    Mit C++ nun, geht das nicht so einfach. Bisher mache ich das so

            if( classname.compare("Form") == 0 )response->control(new Form);
            else response->control(new NotFound);
    
    

    usw. Gibt es eine M├Âglichkeit, den Namen der Klasse variable anzugeben? Danke im Vorab

    und MFG (Mit freundlichen Gr├╝├čen)



  • Erg├Ąnzung: Diese Klassen sind nur Dummies. Also es gibt die schon aber sie sind hohl:

    // Routing Klassen, Pseudoklassen
    class Form{};
    class NotFound{};
    class HTMLfile{};
    class PDFfile{};   // noch nicht fertig
    

    Diese Pseudoklassen (sic) habe ich nur, um die control()-Methode ├╝berlagern zu k├Ânnen. Das erm├Âglicht, mit bestimmten URLs bestimmte Conten-Types auszuliefern und nat├╝rlich auch an verschiedene URLs gebundene verschiedene Parameter-Kontroll-Strukturen (Verarbeitung von Formulareingaben). Des Weiteren erm├Âglicht diese Framework-Architektur das Setzen von Platzhaltern f├╝r bestimmte Webseiten die f├╝r die Ausgabe an den Browser ├╝ber ein Template gerendert werden (dynamische Inhalte).

    In Fakt muss die main nur angepasst werden wenn eine neue Aufgabe betreff Eingabeverarbeitung oder Platzhalter ansteht.

    Vielleicht kann mans aber auch andes machn ­čśë

    MFG



  • Mahlzeit;

    so manche Idee f├╝hrt in eine Sackgasse, das ist normal. Mittlerweile nimmt mein Class-Routing auch in C++ Gestalt an. Wobei es in meinem Fall egal ist, ob ich den Konstruktor einer Klasse aufrufe oder einfach nur eine Funktion. So habe ich mich f├╝r den einfachen Aufruf einer Funktion entschieden, siehe Code untenstehend bez. DateCalc. Auf das Framework bezogen ist DateCalc eine Erweiterung die in einer externen Datei definiert ist.

    #include "DateCalc.cpp"
    //////////////////////////////////////////////////////////////////////////////////////////
    int main(){
        binmode();
        Response response;
        try{
            string classname = response.classname();
            
            if( classname.compare("Form") == 0 )          Form( response );
            else if( classname.compare("Folder") == 0 )   Folder( response );
            else if( classname.compare("HTMLfile") == 0 ) {}
            else if( classname.compare("Env") == 0 )      Env( response );
            else if( classname.compare("DateCalc") == 0 ) DateCalc( response );
            else                                          NotFound( response );
            
            response.start_html();
            response.menu();
            response.body();
            response.footer();
            response.end_html();
        }
        catch(string errstr){
            cout << "Content-Type: text/plain; Charset=utf-8\n\n" << errstr;
            return 1;
        }
    
        // Alles gutgegangen
        cout << response.header();
        cout << response.start_html_buffer  
                + response.menu_buffer 
                + response.body_buffer
                + response.footer_buffer
                + response.end_html_buffer;
    
        return 0;  
    }
    

    Und der Code zeigt auch die Art und Weise der Einbindung anderer Erweiterungen. Das Deployment erfordert eine minimale ├änderung der main mit anschlie├čender Kompilierung. Ich habe f├╝r dieses Beispiel eine etwas ├Ąltere Library, die ich im Jahr 2008 zur Kalenderberechnung in C geschrieben habe wiederbelebt. Wer Interesse daran hat, melde sich einfach.

    Die Webanwendung ist diese da http://rolfrost.de/datecalc.chtml

    Sch├Ânen Sonntag ­čśë



  • F├╝r mich klingt das eher so, als wenn du eine Art Factory br├Ąuchtest.

    Also sowas (ungetestet hier rein getippt)

    class Response {
       virtual std::string header() const = 0;
       ...
    };
    // save name->create instance functions here
    std::map registry<std::string, std::function<std::unique_ptr<Response>()>>; 
    
    
    class DateCalc : public Response {
       ...
    };
    
    class Folder : public Response {
       ...
    };
    
    ...
    
    int main() {
        registry["DateCalc"] = [](){return std::make_unique<DateCalc>();};
        registry["Folder"] = [](){return std::make_unique<Folder>();};
    
        std::string classname = "get it from somewhere";
        auto obj = registry[classname]();
        std::cout << obj->header();
    }
    
    

    Also vom Prinzip eine Map machen, in der man die Name->Klasse Zuordnung speichert. Dann Objekt erzeugen und ausf├╝hren.

    Sicher k├Ânnte man die Resistry jetzt auch kl├╝ger machen. Und au├čerdem ├╝berlegen welche Funktionen man eigentlich will und braucht. Sollen die z.B. alle Strings liefern oder nicht lieber direkt in einen ostream schreiben?



  • @wob ,

    ja so k├Ânnte es auch gehen, danke Dir. Das w├╝rde aber bedeuten, da├č alle Klassen verf├╝gbar sein m├╝ssen und vom Request bis zur Response die Subklasse ├╝bernimmt.

    Mit der jetztigen L├Âsung jedoch gibt es nur einer Responseklasse und damit verfolge ich noch einen anderen Ansatz: Das dynamische Nachladen von Code. Damit meine ich, da├č anstelle der festen Einbindung #include <DateCalc.cpp> eine DLL geladen wird, welche den Code f├╝r die Anwendung definiert. So wird der Code f├╝r die Anwendung nur dann geladen wenn ein Request-URL an diese Klasse gebunden ist. Andererseits, wenn einfach nur HTML-Seiten ausgeliefert werden, wird bspw. DateCalc nicht geladen, ebenso wird eine Instanz der CGI-Klasse auch nur dann erstellt wenn Eingaben (Parameter, POST, PUT usw.) zu verarbeiten sind.

    Ob man dieses dynamische Nachladen von Code auf Klassen oder einfach nur Methoden anwendet ist eine ander Frage.

    Viele Gr├╝├če und einen sch├Ânen Rest-Sonntag ­čśë



  • @_ro_ro Dann kannst du doch einfach in der zu ladenden Library 2 Funktionen anbieten: 1. den Namen, 2. eine Funktion, die das Objekt erzeugt. Dann noch irgendwo eine Konfigurationsdatei und du musst das Hauptprogramm nicht mehr neu erzeugen.



  • @wob sagte in Class Routing:

    @_ro_ro Dann kannst du doch einfach in der zu ladenden Library 2 Funktionen anbieten: 1. den Namen, 2. eine Funktion, die das Objekt erzeugt. Dann noch irgendwo eine Konfigurationsdatei und du musst das Hauptprogramm nicht mehr neu erzeugen.

    Genau das ist das Ziel ­čśë

    Danke Dir und viele Gr├╝├če.


Log in to reply