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 1 von 5  1 23     Letzte »    
Sigi55

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

Routine mit Namen aufrufen

  Alt 20. Feb 2015, 15:56
Hallo,

ich nutze diese kleine Routine um Prozeduren mit Namen zu starten,
das klappt auch alles ganz wunderbar solange sich diese Prozedure
in der gleichen Form befindet ...

Delphi-Quellcode:
type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
    // Your routines (that you'll run by name) must be here
    procedure Hello_World(Sender: TObject);
  private
    procedure ExecuteRoutine(Instance: TObject; Name: string);
  end;

var
  Form1: TForm1;

type
  TExecute = procedure of object;

procedure TForm1.ExecuteRoutine(Instance: TObject; Name: string);
var
  Routine: TMethod;
  Execute: TExecute;
begin
  Routine.Data := Pointer(Instance);
  // Returns the address of a published method.
  Routine.Code := Instance.MethodAddress(Name);
  if Routine.Code = nil then Exit;
  Execute := TExecute(Routine);
  Execute;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExecuteRoutine(Form1, 'Hello_World');
end;

procedure TForm1.Hello_World(Sender: TObject);
begin
  ShowMessage('This is a test');
end;
Jetzt möchte ich von der Hauptform eine Routine (Prozedure) aus einer
anderen unit aufrufen.
Und das bekomm ich nicht gebacken ..., da fehlt's mir echt an den
Grundlagen

Kann mit jemand weiterhelfen ?

Danke schonmal.

Gruß

Sigi
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#2

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 16:09
Jetzt möchte ich von der Hauptform eine Routine (Prozedure) aus einer
anderen unit aufrufen.
Dazu musst Du die andere Unit in die Uses-Klausel eintragen.

Und das bekomm ich nicht gebacken ..., da fehlt's mir echt an den Grundlagen
Dir fehlt es an Grundlagen und möchtest eine Methode über ihren Namen ansprechen?

Warum nicht den normalen Weg?
Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  Hello_World(Self);
end;
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#3

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 16:26
Das hier ist der wichtige Teil:
  // Returns the address of a published method.
Die RTTI (zumindest die nicht erweiterte, die es bei Delphi 5 auch lange noch nicht gab) ist nur bei published Feldern behilflich, alles was nicht published ist, kennt sie einfach nicht. Daher wird der Aufruf auf diese Weise nicht gehen, auch nicht mit Tricks. (Der Teil direkt unter einer Klassendeklaration ausserhalb der "private, protected, public, published"-Sektionen ist implizit published.)
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von stahli
stahli

Registriert seit: 26. Nov 2003
Ort: Halle/Saale
4.336 Beiträge
 
Delphi 11 Alexandria
 
#4

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 16:51
Nenne am besten erst mal konkret Deine Delphi-Version. Delphi5?

Und was willst Du mit der Funktionalität erreichen bzw. was willst Du dem User ermöglichen? Vielleicht gibt es ja bessere Alternativen.

Methoden nach Namen ermitteln und ausführen ist ab D2010 einfacher - aber immer noch recht komplex.

Evtl. kannst Du das auch einfacher lösen:

Delphi-Quellcode:
procedure TForm1.ExecuteRoutine(Instance: TObject; Name: string);
begin
  if (Name = "DoA") and (Instance is TMyClass) then
  begin
    (Instance as TMyClass).DoA;
    Exit;
  end;
  if (Name = "DoB") and (Instance is TOtherClass) then
  begin
    (Instance as TOtherClass).DoB;
    Exit;
  end;
end;
Das geht natürlich nur, wenn die möglichen Klassen und Methoden relativ übersichtlich sind.
Stahli
http://www.StahliSoft.de
---
"Jetzt muss ich seh´n, dass ich kein Denkfehler mach...!?" Dittsche (2004)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 16:53
(Der Teil direkt unter einer Klassendeklaration ausserhalb der "private, protected, public, published"-Sektionen ist implizit published.)
Nein und vielleicht auch ja.

Der Standard ist "public", außer die Klasse oder ein Vorfahre ist mit {$M+} compiliert, wie z.B. TPersistent/TComponent, wo es dann "published" wird.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#6

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 17:48
Der Code funktioniert auch mit 2 Units.

Aber für was er das benötigt ist noch nicht offensichtlich.


Hier mal ein Beispiel mit 2 Units:

1. Unit mit 2 Buttons auf der Form

Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Hello_World(Sender: TObject);
  private
    procedure ExecuteRoutine(Instance: TObject; Name: string);
  public
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  unit2;

type
  TExecute = procedure of object;

procedure TForm1.Button1Click(Sender: TObject);
begin
  ExecuteRoutine(Form1, 'Hello_World');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ExecuteRoutine(Form2, 'Hello_World');
end;

procedure TForm1.ExecuteRoutine(Instance: TObject; Name: string);
var
  Routine: TMethod;
  Execute: TExecute;
begin
  Routine.Data := Pointer(Instance);
  // Returns the address of a published method.
  Routine.Code := Instance.MethodAddress(Name);
  if Routine.Code = nil then Exit;
  Execute := TExecute(Routine);
  Execute;
end;


procedure TForm1.Hello_World(Sender: TObject);
begin
  ShowMessage('Form1.Hello_World');
end;


end.
Und die 2. Unit

Delphi-Quellcode:
unit Unit2;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm2 = class(TForm)
    procedure Hello_World(Sender: TObject);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form2: TForm2;

implementation

{$R *.dfm}

procedure TForm2.Hello_World(Sender: TObject);
begin
  ShowMessage('Form2.Hello_World');
end;

end.
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.679 Beiträge
 
Delphi 2007 Enterprise
 
#7

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 18:56
(Der Teil direkt unter einer Klassendeklaration ausserhalb der "private, protected, public, published"-Sektionen ist implizit published.)
Nein und vielleicht auch ja.

Der Standard ist "public", außer die Klasse oder ein Vorfahre ist mit {$M+} compiliert, wie z.B. TPersistent/TComponent, wo es dann "published" wird.
Da hatter Recht, über diese Falle bin ich sogar auch schon mal gestolpert, wenn auch in einem anderen Zusammenhang.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: Routine mit Namen aufrufen

  Alt 20. Feb 2015, 21:52
Delphi-Quellcode:
procedure TForm1.Hello_World(Sender: TObject);

TExecute = procedure of object;
Und schon hat jemand Mist gebaut, denn die Signaturen stimmen nicht überein.

Zum Glück liegt dieser Parameter zufällig in den Registern und nicht auf'm Stack,
so steht da nur Schrott drin und es knallt nicht gleich.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (20. Feb 2015 um 21:54 Uhr)
  Mit Zitat antworten Zitat
Sigi55

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

AW: Routine mit Namen aufrufen

  Alt 21. Feb 2015, 06:21
Moin erstmal,

also, wozu braucht er das ?

Ich hab mir so eine Art Taskplaner, unix-cron, etc.. geschrieben.
Die jobs lese ich aus einer DB-Tabelle und arbeite sie zeitgesteuert ab.
Der "JobName" ist die Bezeichnung der aufzurufen Procedure den ich per Variable
übergebe.

Das klappt auch alles wunderbar, nur liegen nicht alle Proceduren auf der
Hauptform ...

z.Z. mache ich es über den Umweg

Delphi-Quellcode:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ExecuteRoutine(Form1, Datensicherung);
end;

procedure TForm1.Datensicherung(Sender: TObject);
begin
  DatenSicherungStarten;
end;
... und ich hätte gern etwas inder Art:

ExecuteRoutine(Unit??? oder wo auch immer, Datensicherung);
Das muss zwar alles nicht sein, ist auch kein Akt wenn es so nicht
zu machen ist, wäre nur schöner

Gruß

Sigi
  Mit Zitat antworten Zitat
hanvas

Registriert seit: 28. Okt 2010
157 Beiträge
 
Delphi 11 Alexandria
 
#10

AW: Routine mit Namen aufrufen

  Alt 21. Feb 2015, 08:55
Moin erstmal,

Ich hab mir so eine Art Taskplaner, unix-cron, etc.. geschrieben.
Die jobs lese ich aus einer DB-Tabelle und arbeite sie zeitgesteuert ab.
Der "JobName" ist die Bezeichnung der aufzurufen Procedure den ich per Variable
übergebe.

Sigi
Wenn ich das richtig verstehen dann gibt es keine "unbekannten" Prozeduren und Methoden sondern lediglich Objekte/Klassen die sich auf mehrere Units verteilen und die Du einheitlich aufrufen willst, Du weisst aber wo (in welcher Unit/Klasse) diese Funktionen ursprünglich definiert sind. Da du alle Methoden in Deinem Beispiel ohne Parameter aufrufen wolltest gehe ich davon aus das alle aufzurufenden Methoden paramterlos sind.

In jedem Fall würde ich dafür sorgen das sich die aufzurufenden Objekte/Methoden selbst bei einer zentralen Instanz "registrieren".

Delphi-Quellcode:
  

unit register;

....

type TJobRegister = class(TObject)
     private
       FRegister : TStringList;
     public
       procedure registerCall (const registeredName : String; m : pMethod);
       procedure Call(const registeredName : String);
     end;

function RegisteredJobs : TJobRegister; // singleton für arme

implementation

procedure TJobRegister.registerCall (const registeredName : String; m : pMethod);
begin
 if (FRegister.IndexOf(registeredName)<0) then
     FRegister.AddObject(registeredName,m);
end;

procedure TJobRegister.Call(const registeredName : String);
var idx : Integer;
begin
 idx := FRegister.IndexOf(registeredName);
 if (idx >= 0 ) then begin
                         TExecute(FRegister.Objects[idx]^).Execute;
                     end
                else begin
                       .....
                     end;
end;
Die Klassen deren Methoden aufgerufen werden sollen müssten dann die Unit Register verwenden und sich dort anmelden, beispielsweise so

Delphi-Quellcode:
  

uses Register;

type TUseable = class(TObject)
     public
      constructor Create;
      procedure TuWas;
     end;

constructor TUseable.Create;
var m : pMethod;
begin
 New(m);
 m.Data := self;
 m.Code := @TuWas;
 register.registeredJobs.registerCall('Irgendwas',m);
end;
Das hätte auch den Vorteil das Du beliebige Namen verwenden kannst. Die Registerklasse müsste sich freilich noch um die Freigabe der pMethod Variablen kümmern, eine Deregistrierung wäre angeraten wenn es passieren kann das Instanzen während der Laufzeit des Programmes zerstört werden etc. Aber wenn Du das so machst, dann kannst Du es auch gleich richtig machen und entweder Interfaces verwenden oder Dir einen Wrapper je aufzurufender Klasse schreiben und dessen Instanzen / Objekte registrieren.

cu Ha-Jö
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 5  1 23     Letzte »    


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 23:45 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