|
christian_r
(Gast)
n/a Beiträge |
#1
Guten Morgen.
Ich entwickle quasi gerade ein Kommando-MVC für eine Remote-GUI. Meine Zielsetzung: Über das Eingabefeld des Formulars werden Konsolenkommandos nach dem Schema 'Klasse-Methode-Parameter' eingegeben. (Bestätigung der Eingabe mit Return.) Diese Kommandos werden an den CommandWrapper weitergegeben. Dort wird in der Methode 'GetPlugin' mittels 'GetClass( )' die generische Klasse ermittelt und eine Instanz davon erzeugt und zurückgegeben. Somit kann man das ganze System um weitere Klassen wie die Klasse 'TOCommandPluginProcess' in der Unit 'oCommandPluginProcess.pas' erweitern, ohne den Code des Wrappers erst erweitern zu müssen. Alle Klassen 'TOCommandPluginXXX' müssen mindestens von der Klasse 'TOCommandPluginWrapper' abgeleitet werden und müssen mit 'RegisterClass( )' verfügbar gemacht werden. Wurde die Klasse gefunden und instanziert, dann wird deren virtuelle Methode 'Execute( )' in 'TOCommandPluginWrapper' aufgerufen, welcher die verbliebenen Parameter ohne die Angabe der Klasse übergeben werden. (Es ist dann nur noch das Kommando 'Methode-Parameter' übrig.) In dieser Methode wird versucht die Methode mit 'MethodAddress( )' zu ermitteln. Wurde sie gefunden, dann wird Sie aufgerufen. Nun bin ich an der Fehlerquelle angelangt. In der Klasse 'TOCommandPluginWrapper' ist eine Eigenschaft 'Params : TAString' als 'protected' deklariert. Diese ist dann eigentlich in allen davon abgeleiteten Klassen verfügbar. Nachdem nun die Methode mit 'MethodAddress( )' ermittelt wurde, werden alle verbliebenen Parameter ohne den Methodenbezeichner in der Eigenschaft 'Params' gespeichert, da ich diese über 'MethodAddress( )' nicht übergeben kann. Anschließend wird die gefundene Methode in über die Variable 'MethodCaller' aufgerufen. Der Aufruf der Default-Eingabe bei Programmstart funktioniert - die Testausgabe muss 'Inside Test: 0' lauten. Es gibt zwei Auslöser für eine Exception. Entfernt man die Kommentierung von 'ShowMessage' vor dem Aufruf der Methode mittels 'MethodCall', dann löst die Testausgabe in 'TOCommandPluginProcess.Test( )' eine Exception aus. Lässt man den Kommentar bestehen und fügt hinter der Standardeingabe 'process test' noch einen oder mehrere fiktive Parameter an, dann löst die Testausgabe ebenfalls eine Exception aus. Es liegt definitiv am Zugriff auf 'Self.Params'. Ich verstehe dieses Problem leider nicht, weil es "eigentlich" nicht auftreten dürfte. Aber es muss ja einen sinnvollen Grund dafür geben. Ich weiß nicht, ob es am Aufruf der Methoden mittels 'MethodAddress( )', oder evtl. an den generischen Klassen liegt. Hier nun die Quellcodes, einmal gepostet und einmal das Projekt zum direkten Testen als Angang. Entscheidend sind die Units 'oCommandPluginWrapper' (dort die Methode 'Execute') und 'oCommandPluginProcess' (dort die Methode 'Test'). Ich hoffe, ich habe das Problem verstädnlich und ausführlich genug beschrieben. uFormModules.pas
Delphi-Quellcode:
oCommandWrapper.pas
unit uFormModules;
interface uses Windows, Forms, Classes, Dialogs, StdCtrls, Controls; type TFormModules = Class( TForm ) BxGrpConsole : TGroupBox; EdtConsole : TEdit; procedure EdtConsoleKeyDown ( Sender : TObject; var Key : Word; Shift: TShiftState ); private procedure ExecuteCommand ( const pCommand : String ); virtual; end; var FormModules : TFormModules; implementation uses SysUtils, oCommandWrapper, XtSystem; {$R *.dfm} // Private procedure TFormModules.ExecuteCommand ( const pCommand : String ); var CommandWrapper : TOCommandWrapper; Command : String; begin CommandWrapper := TOCommandWrapper.Create( Self ); Command := pCommand; ShowMessage( CommandWrapper.Execute( Command ) ); CommandWrapper.Free( ); end; procedure TFormModules.EdtConsoleKeyDown ( Sender : TObject; var Key : Word; Shift : TShiftState ); begin if Key = VK_RETURN then begin Self.ExecuteCommand( Self.EdtConsole.Text ); Self.EdtConsole.Clear( ); end; end; end.
Delphi-Quellcode:
oCommandPluginWrapper.pas
unit oCommandWrapper;
interface uses Classes, oCommandPluginWrapper, XtSystem; type TOCommandWrapper = Class( TComponent ) private function GetPlugin ( const pClassName : String ) : TOCommandPluginWrapper; virtual; procedure AddParam ( var pParams : TAString; const pParam : String ); virtual; public function Execute ( pCommand : String ) : String; virtual; end; implementation uses SysUtils; // Private function TOCommandWrapper.GetPlugin ( const pClassName : String ) : TOCommandPluginWrapper; var CommandPlugin : TCCommandPluginWrapper; begin CommandPlugin := TCCommandPluginWrapper( GetClass( pClassName ) ); if Assigned( CommandPlugin ) then Result := CommandPlugin.Create( ) else Result := nil; end; procedure TOCommandWrapper.AddParam ( var pParams : TAString; const pParam : String ); begin SetLength( pParams, Length( pParams ) + 1 ); pParams[ High( pParams ) ] := pParam; end; // Public function TOCommandWrapper.Execute ( pCommand : String ) : String; var CommandPlugin : TOCommandPluginWrapper; Command : String; Params : TAString; ParamPos : Integer; begin // Parameter als dyn. Array (Typ: TAString) zusammenstellen pCommand := Trim( pCommand ); Params := nil; ParamPos := Pos( #32, pCommand ); if ParamPos = 0 then Command := pCommand else begin Command := Copy( pCommand, 1, ParamPos - 1 ); Delete( pCommand, 1, ParamPos ); while Length( pCommand ) > 0 do begin ParamPos := Pos( #32, pCommand ); if ParamPos = 0 then begin Self.AddParam( Params, pCommand ); pCommand := ''; end else begin Self.AddParam( Params, Copy( pCommand, 1 , ParamPos - 1 ) ); Delete( pCommand, 1, ParamPos ); end; end; end; // ermitteln der Klasse und Aufruf derer virtuellen Methode 'Execute' bzw. Abbruch mit Fehlermeldung CommandPlugin := Self.getPlugin( 'TOCommandPlugin' + Command ); if not Assigned( CommandPlugin ) then begin Result := 'Unknown command!' + #10 + Command; Exit; end else begin Result := CommandPlugin.Execute( Params ); CommandPlugin.Free( ); end; end; end.
Delphi-Quellcode:
oCommandPluginProcess.pas
unit oCommandPluginWrapper;
interface uses Classes, XtSystem; type TOCommandPluginWrapper = Class( TPersistent ) protected Params : TAString; public function Execute ( const pParams : TAString ) : String; virtual; end; TCCommandPluginWrapper = Class of TOCommandPluginWrapper; implementation uses dialogs, SysUtils; // Public function TOCommandPluginWrapper.Execute ( const pParams : TAString ) : String; var MethodCaller : TProcedure; begin if Length( pParams ) = 0 then Result := '' else begin MethodCaller := Self.MethodAddress( pParams[ 0 ] ); if Assigned( MethodCaller ) then begin Self.Params := Copy( pParams, 1, Length( pParams ) ); ShowMessage( 'Before: ' + IntToStr( Length( Self.Params ) ) ); MethodCaller; end else Result := 'Unknown method!' + #10 + pParams[ 0 ]; end; end; end.
Delphi-Quellcode:
Ich habe den eigentlichen Code auf das Wesentliche zusammengeschröpft und kommentiert. Hoffentlich gibt es bei Euch Interesse, da mal reinzuschauen.
unit oCommandPluginProcess;
interface uses Classes, XtSystem, oCommandPluginWrapper; type TOCommandPluginProcess = Class( TOCommandPluginWrapper ) published procedure Test ( ); virtual; end; implementation uses dialogs, sysutils; procedure TOCommandPluginProcess.Test ( ); begin // hier wird die Exception ausgelöst ShowMessage( 'Inside ''Test'': ' + IntToStr( Length( Self.Params ) ) ); end; begin RegisterClass( TOCommandPluginProcess ); end. Danke. |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |