Frage

Wir versuchen, eine API zu bauen, um Unterstützung commit () und rollback () automatisch, so dass wir damit nicht mehr haben zu stören. Durch die Erforschung, haben wir, dass die Verwendung eval {} ist der Weg zu gehen gefunden.

Für eval {} zu wissen, was zu tun, ich habe gedacht, die API eine Reihe von Funktionen geben, die es mit einem foreach ohne die API mit zu intepret allem ausführen kann. Allerdings könnte diese Funktion in einem anderen Paket sein.

Lassen Sie mich mit einem Beispiel verdeutlichen:

sub handler {
    use OSA::SQL;
    use OSA::ourAPI;
    my @functions = ();
    push(@functions, OSA::SQL->add_page($date, $stuff, $foo, $bar));
    my $API = OSA::ourAPI->connect();
    $API->exec_multi(@functions);
}

Die Frage ist: Ist es möglich, die Funktionen in @functions innerhalb von OSA::ourAPI auszuführen, auch wenn ourAPI keine use OSA::SQL hat. Wenn nicht, wäre es möglich, wenn ich ein Array Referenz verwenden anstelle eines Arrays gegeben, dass der Zeiger auf die bekannte Funktion innerhalb des Speichers zeigen würde?

Hinweis: Dies ist die Grundidee, dass wir die komplexeren Endfassung auf

basieren sollen.
War es hilfreich?

Lösung


  • Sie fügen keine Funktion Zeiger auf das Array. Sie fügen teh Rückgabewert die add_page () Unterprogramm aufgerufen wird. Sie haben 3 Lösungen für diese:

    A. Sie werden (in @functions) eine Reihe von arrayrefs der Form [\&OSA::SQL::add_page, @argument_values] speichern müssen, können Sie in einem aktuellen Bezug zu einem Unterprogramm übergeben Sinn (so genannten statisch); und dann tut exec_multi so etwas wie (Syntax möglicherweise nicht 100% richtig, wie es der 04.00 hier)

    sub exec_multi {
        my ($class, $funcs)= @_;
        foreach my $f (@$funcs) {
            my ($func, @args) = @$f;
            my $res = &$func(@args);
            print "RES:$res\n";
        }
    }
    

    Just, erneut auf, diese einzelne U-Boote in statischer Version nennen (OSA::SQL::add_page), z.B. OHNE die Paketnamen als erste Parameter als Klasse Anruf OSA::SQL->add_page vorbei wäre. Wenn Sie die letzte möchten, finden Sie die nächste Lösung.


    B. Wenn Sie Ihre U-Boote in der Klasse Kontext nennen (wie in Ihrem Beispiel, mit anderen Worten mit dem Klassennamen als erster Parameter), können Sie ysth Vorschlag im Kommentar verwenden.

    Sie speichern müssen (in @functions) eine Reihe von arrayrefs der Form [sub { OSA::SQL->add_page(@argument_values) }], Sie in einem Verweis auf ein Unterprogramm übergeben bedeutet, was wiederum Anruf, was Sie brauchen; und dann tut exec_multi so etwas wie (Syntax möglicherweise nicht 100% richtig, wie es der 04.00 hier)

    sub exec_multi {
        my ($class, $funcs)= @_;
        foreach my $f (@$funcs) {
            my ($func) = @$f;
            my $res = &$func();
            print "RES:$res\n";
        }
    }
    

    C. Sie werden (in @functions) eine Reihe von arrayrefs der Form [ "OSA::SQL", "add_page", @argument_values] speichern müssen, können Sie in einem Paket und Funktionsnamen übergeben Sinn; und dann tut exec_multi so etwas wie (Syntax möglicherweise nicht 100% richtig, wie es der 04.00 hier)

    my ($package, $sub, @args) = @{ $functions[$i] };
    no strict 'refs';
    $package->$sub(@args);
    use strict 'refs';
    

  • Wenn ich Ihre Frage richtig verstanden, dann brauchen Sie sich keine Sorgen machen, ob ourAPI verwendet OSA :: SQL, da Ihr Hauptcode importiert sie bereits.

    Da jedoch - in # 1B - Sie erhalten eine Liste der Pakete exec_multi als erste Elemente jeder ArrayRef werden geben, können Sie „require $package; $package->import();“ in exec_multi tun. Aber noch einmal, es ist völlig un-nötig, wenn Ihr Handler Aufruf bereits erforderlich und geladen jedes dieser Pakete. Und es richtig machen müssen Sie auch in einer Liste von Parametern zu import() passieren. ABER WHYYYYYY? :)

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top