AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Routine mit Namen aufrufen

Ein Thema von Sigi55 · begonnen am 20. Feb 2015 · letzter Beitrag vom 25. Feb 2015
Antwort Antwort
Seite 4 von 5   « Erste     234 5      
Sigi55

Registriert seit: 3. Jan 2010
36 Beiträge
 
Delphi 5 Professional
 
#31

AW: Routine mit Namen aufrufen

  Alt 22. Feb 2015, 21:47
Hallo,

Mann-O-Mann, da hab ich ja was losgetreten ...

Ich würd ja gern den Ansatz von Ha-Jö testen, aber ich kann das
nicht ausprogrammieren ..., das ist für mich zu weit im Eingemachten.

Mit dem Ansatz von BadenPower komm ich klar.

Vielleicht hat ja jemand Lust, Zeit, Ruhe und Muße die bessere Lösung
als fertiges Beispiel zu bauen ??

Gruß

Sigi
  Mit Zitat antworten Zitat
hanvas

Registriert seit: 28. Okt 2010
168 Beiträge
 
Delphi 11 Alexandria
 
#32

AW: Routine mit Namen aufrufen

  Alt 23. Feb 2015, 16:57

Ich würd ja gern den Ansatz von Ha-Jö testen, aber ich kann das
nicht ausprogrammieren ..., das ist für mich zu weit im Eingemachten.
Ich hatte Dir doch schon fast alles geliefert. Hier nochmal die Komfortvariante.

Delphi-Quellcode:

unit jRegister;
interface
uses classes;

type TJobRegister = class(TComponent)
     private
      FRegister : TStringList;
     public
      Constructor Create(aOwner : TComponent); override;
      Destructor Destroy; override;

      procedure RegisterObjectMethods
       (Instance : TObject; const methods : TStrings); virtual;

      procedure RegisterObjectMethodByName
       (const registeredName : String; Instance : TObject; const method : String);
                                                                                virtual;
      procedure RegisterObjectMethod
        (const registeredName : String; instance : TObject; addr : Pointer); virtual;
      procedure RegisterCall (const registeredName : String; m : pMethod); virtual;
      procedure UnRegisterCall (const registeredName : String); virtual;
      procedure Call(const aFunctionToCall : String); virtual;
     end;

     TExecute = procedure of object;

function jobRegister : TJobRegister;

implementation
uses sysUtils;

var reg : TJobRegister = nil;

function jobRegister : TJobRegister;
begin
 if not Assigned(reg) then
    reg := TJobRegister.Create(Application);
 result := reg;
end;

Constructor TJobRegister.Create(aOwner : TComponent);
begin
 inherited Create(aOwner);
 FRegister := TStringList.Create;
 FRegister.Sorted := True;
end;

Destructor TJobRegister.Destroy;
var i : Integer;
    p : pMethod;
begin
 for i := 0 to FRegister.Count-1 do
  begin
    p := pMethod(FRegister.Objects[i]);
    FreeMem(p);
  end;
end;

procedure TJobRegister.RegisterObjectMethods
       (Instance : TObject; const methods : TStrings);
var i : Integer;
  n,v : String;
begin
 for i := 0 to methods.count-1 do
  begin
    n := methods.Names[i];
    v := methods.Values[n];
    if (n<>'') and
       (v<>'') then
         RegisterObjectMethodByName(n,instance,v);
  end;
end;

procedure TJobRegister.RegisterObjectMethodByName
       (const registeredName : String; Instance : TObject; const method : String);
var p : Pointer;
begin
 if Assigned(instance) then
  begin
   p := Instance.MethodAddress(method);
   if (Assigned(p)) then
       RegisterObjectMethod(registeredName,Instance,p);
  end;
end;


procedure TJobRegister.RegisterObjectMethod
        (const registeredName : String; instance : TObject; addr : Pointer);
var p : pMethod;
begin
 GetMem(p,SizeOf(TMethod));
 p.Data := instance;
 p.Code := addr;
 RegisterCall(registeredName,p);
end;

procedure TJobRegister.RegisterCall (const registeredName : String; m : pMethod);
begin
    if (FRegister.IndexOf(registeredName)<0) then
        FRegister.AddObject(registeredName,Pointer(m))
    else raise Exception.Create('Funktion [' + registeredName + '] bereits registriert');
end;

procedure TJobRegister.UnRegisterCall (const registeredName : String);
var idx : Integer;
    p : pMethod;
begin
 idx := FRegister.IndexOf(registeredName);
 if (idx >= 0 ) then begin
                       p := pMethod(FRegister.Objects[idx]);
                       FreeMem(p);
                     end
                else raise Exception.Create('Ungültiger Versuch [' + registeredName + '] freizugeben');
end;

procedure TJobRegister.Call(const aFunctionToCall : String);
var idx : Integer;
    p : pMethod;
    e : TExecute;
begin
 idx := FRegister.IndexOf(aFunctionToCall);
 if (idx >= 0 ) then begin
                         p := Pointer(FRegister.Objects[idx]);
                         e := TExecute(p^);
                         e();
                     end
                else begin
                       raise Exception.Create('Funtkion [' + aFunctionToCall + '] nicht vorhanden');
                     end;
end;
Die aufzurufenden Routinen musst Du aber selbst verpacken. Das geht aber ziemlich einfach. Das nachfolgende Beispiel zeigt wie.


Delphi-Quellcode:

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
  public
    { Public-Deklarationen }
  published
    procedure execute1;
    procedure execute2;
    procedure execute3;
    procedure execute4;
  end;

var
  Form1: TForm1;

implementation
uses jRegister;

{$R *.dfm}

procedure TForm1.execute1;
begin
 MessageDlg('Test', mtWarning, [mbOK], 0);
end;

procedure TForm1.execute2;
begin
 MessageDlg('Test 2', mtWarning, [mbOK], 0);
end;

procedure TForm1.execute3;
begin
 MessageDlg('Test 3', mtWarning, [mbOK], 0);
end;

procedure TForm1.execute4;
begin
 MessageDlg('Test 4', mtWarning, [mbOK], 0);
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
 reg := TJobRegister.Create(self);
end;

procedure TForm1.Button1Click(Sender: TObject);
var s : TStringList;
begin
  s := TStringList.Create;
  s.Add('Test=execute1');
  s.Add('Test2=execute2');
 { methoden müssen published sein, Instance muss von TPersistent
   oder TComponent abgeleitet sein }

  jobRegister.RegisterObjectMethods(self,s);
  s.free;

  jobRegister.Call('Test');
  jobRegister.Call('Test2');

 { Instanzen können beliebige Objekte sein, Methoden müssen nicht published sein }
  jobRegister.RegisterObjectMethod('Test 3', self, @TForm1.execute3);
  jobRegister.Call('Test 3');

  { methoden müssen published sein, Instance muss von TPersistent
   oder TComponent abgeleitet sein }

  jobRegister.RegisterObjectMethodByName('Test 4', self, 'execute4' );
  jobRegister.Call('Test 4');
end;

end.
Die Funktion jobregister ist zentral definiert und sollte nur einmal vorhanden. Die Methoden die verpackt werden sollen dürfen in beliebigen anderen Objekten sein, die nicht zwingend von TComponent oder TPersistent abgeleitet sein müssen. Das Registrieren und Deregistrieren von Methoden wäre am besten im Constructor bzw. Destrukter der Objekte untergebracht die diese Methoden aufrufen - das Beispiel ist aber so das Du es verstehen solltest und ähnlich wie das bis jetzt von Dir verwendete.

Schön ist aber trotzdem anders.
  Mit Zitat antworten Zitat
hanvas

Registriert seit: 28. Okt 2010
168 Beiträge
 
Delphi 11 Alexandria
 
#33

AW: Routine mit Namen aufrufen

  Alt 23. Feb 2015, 20:43
Habe leider zwei Fehler eingebaut. Bei Destroy fehlt der geerbte Destructor also bitte lieber so:

Delphi-Quellcode:


Destructor TJobRegister.Destroy;
var i : Integer;
    p : pMethod;
begin
 for i := 0 to FRegister.Count-1 do
  begin
    p := pMethod(FRegister.Objects[i]);
    FreeMem(p);
  end;
 inherited Destroy;
end;

und im Beispiel gehört sich FormCreate gestrichen.
  Mit Zitat antworten Zitat
Sigi55

Registriert seit: 3. Jan 2010
36 Beiträge
 
Delphi 5 Professional
 
#34

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 00:15
Hallo Ha-Jö !!

ist ja der Wahnsinn, was für ne Arbeit

Delphi-Quellcode:
Destructor TJobRegister.Destroy;
var i : Integer;
    p : pMethod; // Mag er nicht, Undeclared Indentifier ????
begin
 for i := 0 to FRegister.Count-1 do
  begin
    p := pMethod(FRegister.Objects[i]);
    FreeMem(p);
  end;
 inherited Destroy;
end;
Sonst sieht alles gut aus, aber ich hab keine Ahnung was ich mit "pMethod"
machen soll ...

Danke für die Mühe, jetzt soll's aber auch laufen !

Gruß

Sigi

P.S.: ist D2010
  Mit Zitat antworten Zitat
Benutzerbild von DeddyH
DeddyH

Registriert seit: 17. Sep 2006
Ort: Barchfeld
27.624 Beiträge
 
Delphi 12 Athens
 
#35

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 08:03
Ich rate mal:
Delphi-Quellcode:
type
  pMethod = ^TMethod;
Detlef
"Ich habe Angst vor dem Tag, an dem die Technologie unsere menschlichen Interaktionen übertrumpft. Die Welt wird eine Generation von Idioten bekommen." (Albert Einstein)
Dieser Tag ist längst gekommen
  Mit Zitat antworten Zitat
Sigi55

Registriert seit: 3. Jan 2010
36 Beiträge
 
Delphi 5 Professional
 
#36

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 17:46
Moin,

mir sagt das Alles garnichts und wird es auch wohl nie ...

Delphi-Quellcode:
  procedure RegisterCall (const registeredName : String; m : pMethod); virtual;
                                                             ^^^^^^^
// Mag er nicht, Undeclared Indentifier ???

Ich kann mir da leider nicht ansatzweise weiterhelfen, da hört's
echt auf.
Ich bin mehr so der Datenschauffler im kfm. Bereich, so von einer DB
in die andere, Plausibilitätsprüfungen, etc.

Aber das ist nicht meine Welt ... sry.

@DaddyH, das war es leider nicht

Gruß

Sigi
  Mit Zitat antworten Zitat
hanvas

Registriert seit: 28. Okt 2010
168 Beiträge
 
Delphi 11 Alexandria
 
#37

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 18:28
Moin,

mir sagt das Alles garnichts und wird es auch wohl nie ...

Delphi-Quellcode:
  procedure RegisterCall (const registeredName : String; m : pMethod); virtual;
                                                             ^^^^^^^
// Mag er nicht, Undeclared Indentifier ???

@DaddyH, das war es leider nicht

Gruß

Sigi
Doch natürlich war es das! Aber eigentlich sollte pMethod in der Unit system ohnehin deklariert sein, möglicherweise ist das von Version zu Version unterschiedlich.

Wo hast Du das

  type pMethod = TMethod; denn hingeschrieben. Dir Typdeklaration gehört vor die erste Verwendung also

Delphi-Quellcode:

unit jRegister;
interface
uses classes;

type pMethod = TMethod;

     TJobRegister = class(TComponent)
 .....
cu Ha-Jö
  Mit Zitat antworten Zitat
Sigi55

Registriert seit: 3. Jan 2010
36 Beiträge
 
Delphi 5 Professional
 
#38

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 19:43
Hi,

Zitat:
... denn hingeschrieben. Dir Typdeklaration gehört vor die erste Verwendung also
Delphi-Quellcode:

unit jRegister;
interface
uses classes;

type pMethod = TMethod;

     TJobRegister = class(TComponent)
 .....
Hatte ich auch so gemacht, nur hatte ich "type pMethod = ^TMethod" wie DaddyH
es geschrieben hatte ...

Jetzt, ohne "^" ist es OK, nur eines noch ..

Delphi-Quellcode:
function jobRegister : TJobRegister;
begin
 if not Assigned(reg) then
    reg := TJobRegister.Create(Application);
 result := reg; // ^^^^^^^^^^^
end;
Fehler: Application? Undeclared Indentifier ???

Das ist jetzt aber der Letzte ...

Und nochmal für Blö..., wo genau an welcher Stelle soll das
"FormCreate" gestrichen werden ??

Danke

Sigi
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.071 Beiträge
 
Delphi 12 Athens
 
#39

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 20:19
Fehler: Application? Undeclared Indentifier ???
[F1] kennst du aber?

Delphi-Referenz durchsuchenApplication -> http://docwiki.embarcadero.com/Libra...ms.Application
In der Hilfe steht, in welcher Unit etwas steht.

Aber man muß hier nicht Application verwenden, denn dem Delphi-Referenz durchsuchenTComponent.Create gibt man einen Owner mit, also den, welcher sich um das Freigeben kümmert.
Meistens nimmt man die Form, aber es kann jeder TComponent-Nachfahre sein, oder wenn man sich definitiv immer selber um die Freigabe kümmert, dann kann man auch nil nehmen.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
hanvas

Registriert seit: 28. Okt 2010
168 Beiträge
 
Delphi 11 Alexandria
 
#40

AW: Routine mit Namen aufrufen

  Alt 25. Feb 2015, 20:37
Zitat:

Hatte ich auch so gemacht, nur hatte ich "type pMethod = ^TMethod" wie DaddyH
es geschrieben hatte
Es gehört sich mit ^, das Fehlen war Prellen meiner Tastatur.


Delphi-Quellcode:
function jobRegister : TJobRegister;
begin
 if not Assigned(reg) then
    reg := TJobRegister.Create(Application);
 result := reg; // ^^^^^^^^^^^
end;
Zitat:

Fehler: Application? Undeclared Indentifier ???
Du musst die Unit Forms einbinden wenn Du Application verwenden willst.

Zitat:

Und nochmal für Blö..., wo genau an welcher Stelle soll das
"FormCreate" gestrichen werden ??
Mein ursprüngliches Posting bestand aus einer Unit jRegister und einer in der ein Formular zu Testzwecken verwendet wurde. In der Unit der ich das Formular zum Testen hatte, hatte ich auch "Quickn Dirty" enen Aufruf/Implementierung von FormCreate der nicht reingehört bzw nicht mehr notwendig ist. Wenn Du dieses Testformular nicht nachbaust und nur die andere Unit verwendest dann gibt es kein auch kein FormCreate.

Entschuldige die Fehler die beim Copy / Paste entstanden sind (bzw. das Fehlen von PMethod ist bei meinem Delphi kein Fehler)

cu Ha-Joe
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 4 von 5   « Erste     234 5      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:43 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz