Einzelnen Beitrag anzeigen

Der schöne Günther

Registriert seit: 6. Mär 2013
5.366 Beiträge
 
Delphi 10 Seattle Enterprise
 
#4

AW: Attribute einer Methode in Methode abfragen

  Alt 3. Feb 2018, 19:49
Ich hatte genau den gleichen Gedanken in vor längerer Zeit auch [1]. Auch hier hatte ich die Idee das mit Attributen festzulegen.

Letzten Endes sind wir damit echt nicht glücklich geworden. Nicht nur hat das im eigentlichen Quelltext nichts zu suchen: Klasse X kümmert sich um eine bestimmte Aufgabe, gut ist. Welcher Benutzer zu welcher Uhrzeit bei welcher Mondkonstellation was aufrufen darf sind echt cross-cutting concerns.

Vor allem schmälert das die Wiederverwendbarkeit - Vielleicht kannst du genau die gleiche Klasse in einer anderen Anwendung gebrauchen, aber entweder gibt es hier keins oder ein völlig anderes Rechtesystem.

Wir haben das so umgesetzt dass die ganze Rechte-Geschichte völlig simpel ist: Jede Aktion hat eine String-ID, und zu diesem String lässt sich nachschlagen welcher "Benutzerleven" das aufrufen darf. Darum kümmert sich derjenige der die Methode aufruft, in der Regel ist das ein Bestandteil der Oberfläche. Ganz vereinfacht:

Delphi-Quellcode:
Unit Permissions.IDs;

interface
   const SPECIAL_JOB = 'SPECIAL_JOB';
specialJobButton.Enabled := rightsManager.canInvoke(currentUser, SPECIAL_JOB);


Möchtest du die Rechte-Validierung trotzdem direkt in die Klasse selbst packen hier ein paar Gedanken:

Namen der aktuellen Methode bestimmen
Die Sache hat sicher noch einen Haken, aber mit einem TVirtualMethodInterceptor aus System.Rtti könnte man das machen:

Delphi-Quellcode:
uses
  System.SysUtils,
  System.Rtti;

type
   TMyObject = class
      private var
         interceptor: TVirtualMethodInterceptor;
      private
         procedure handleBefore(
            Instance: TObject;
            Method: TRttiMethod;
            const Args: TArray<TValue>;
            out DoInvoke: Boolean;
            out Result: TValue
         );
         procedure handleAfter(
            Instance: TObject;
            Method: TRttiMethod;
            const Args: TArray<TValue>;
            var Result: TValue
         );
      protected var
         currentMethodName: String;
      public
         constructor Create();
         destructor Destroy(); override;
         procedure IKnowMyName(); virtual;
         procedure IDoNotKnowMyName();
   end;

constructor TMyObject.Create();
begin
   inherited Create();
   interceptor := TVirtualMethodInterceptor.Create( ClassType() );
   interceptor.OnBefore := handleBefore;
   interceptor.OnAfter := handleAfter;
   interceptor.Proxify(self);
end;

destructor TMyObject.Destroy();
begin
   if Assigned(interceptor) then
      begin
         interceptor.Unproxify(self);
         interceptor.Destroy();
      end;
   inherited Destroy();
end;

procedure TMyObject.handleBefore(
   Instance: TObject;
   Method: TRttiMethod;
   const Args: TArray<TValue>;
   out DoInvoke: Boolean;
   out Result: TValue
);
begin
   DoInvoke := True;
   currentMethodName := Method.Name;
end;

procedure TMyObject.handleAfter(
   Instance: TObject;
   Method: TRttiMethod;
   const Args: TArray<TValue>;
   var Result: TValue
);
begin
   currentMethodName := EmptyStr;
end;

procedure TMyObject.IKnowMyName();
begin
   WriteLn( currentMethodName.QuotedString() );
end;

procedure TMyObject.IDoNotKnowMyName();
begin
   WriteLn( currentMethodName.QuotedString() );
end;

Ebenfalls kannst du deine Methode mit dem Exception werfen verwenden: Der TVirtualMethodInterceptor hat ein OnException-Event: Wenn deine spezielle Exception geworfen wurde könnte er die schlucken und deine Methode tut einfach überhaupt nichts.

Analog hat das OnBefore-Event ja auch den Parameter Method: TRttiMethod . Es gibt TRttiMethod.GetAttributes() ! Hier kannst du dir alle Attribute der aktuell aufgerufenen Methode anschauen. Damit kämst du auch ans Ziel.


Nur wie gesagt, ich persönlich würde es so nicht mehr machen. So etwas gehört nicht in die eigentliche Klasse, das "verschmutzt" nur den eigentlichen Code.



[1] http://www.delphipraxis.net/175990-b...en-rechte.html
  Mit Zitat antworten Zitat