Giter VIP home page Giter VIP logo

command-delphi's Issues

Document TAsynCommand

Updated main README with:

  • usage of TAsynCommand (general information)
  • sample implementation (copy this topic to doc ver 1.0)
  • sample execution (copy this topic to doc ver 1.0)

Add Empty injecton as default value in the factory methods

class function CreateCommand<T: TCommand>(AOwner: TComponent;
const Injections: array of const): T;
class procedure ExecuteCommand<T: TCommand>(const Injections
: array of const);
class function CreateCommandAction<T: TCommand>(AOwner: TComponent;
const ACaption: string; const Injections: array of const): TAction;

type
  TCommandVclFactory = class(TComponent)
    // ...
    class function CreateCommand<T: TCommand>(AOwner: TComponent;
      const Injections: array of const = []): T;

[TCommandAction] Rename SetupSomethig => WithSomethig

  1. Change methods of TCommandAction: SetupSomething => WithSomething
  2. Update documentation

Methods list:

  • SetupCaption => WithCaption
  • SetupCommand => WithCommand
  • SetupShortCut => WithShortCut
  • SetupEventOnUpdate => WithEventOnUpdate
  • SetupEventAfterExecution => WithEventAfterExecution
  • Inject => WithInjection

Add TCommandAction.SetupEventOnUpdate

function TCommandAction.SetupEventOnUpdate (TProc<TCommandAction>): TCommandAction;

Button2.Action := TCommandAction.Create(Self)
  .SetupCaption('Run command: Button2')
  .SetupCommand(TSampleCommand.Create(Self))
  .SetupShotcut( TextToShortCut('CTRL+K') )
  .SetupEventOnUpdate(procedure (act: TComanndAction)
    begin
      act.Enable := (Memo1.Lines > 1)
    end)
  .InjectToCommand([Memo1, Edit1])
);

Update signature in components

Remove release date from:

  • Pattern.Command.pas

Change ReleaseVersion to Version in:

  • Pattern.Command.pas

Add siganture to:

  • TCommandAction.pas

Update README do version 1.0

(Review current documentation and add missing points)

List:

  1. Section [TCommand memory management]
    • TBD: Describe advantages of management base on TComponent solution using owner.
  2. Updated and expand TAsyncCommand documentation
    • Events list
    • sample
  3. TCommandAction refactoring:
    • SetupCaption => WithCaption
    • SetupCommand => WithCommand
    • SetupShortCut => WithShortCut
    • SetupEventOnUpdate => WithEventOnUpdate
    • SetupEventAfterExecution => WithEventAfterExecution
    • Inject => WithInjection
  4. TAsyncCommand events:
    • WithEventBeforeStart
    • WithEventAfterFinish
    • thread name for the debugging
      • fThread.NameThreadForDebugging('TAsyncCommand - '+Self.ClassName);
  5. TAsyncCommand - OnUpdate with TTimer
    • WithEventOnProgress(aProc)
    • property ProgressInterval: integer;
    • function GetElapsedTime: TTimeSpan;
  6. All Commands:
    • IsBusy function
    • GetElapsedTime / GetElapsedTimeMs
  7. TAsyncCommand.Terminate

Command add ElapsedTime

type
  TCommand = class
    function GetElapsedTime: TTimeSpan;
    function GetElapsedTimeMs: Integer;

Redesign TComand construction

Remove command construction code from: TCommandVclFactory class:
move to TCommand class

  1. Create command
    • TCommandVclFactory.CreateCommand<TMyCommand>(Owner,[injections...])
    • change to
    • TMyCommand.CreateAndInject(Owner,[injections...])
  2. Execute command
    • TCommandVclFactory.ExecuteCommand<TMyCommand>([injections...]);
    • change to
    • TCommand.Execute<TMyCommand>([injections...]);

Separate Tests into two classes

  • TCommandFactoryTests =>
    • TFactoryNoInjectionTest
    • TFactoryWithInjectionTest

(maybe saperate units too) - now is too early IMHO

Rename methods in TCommandAction

SetupCaption => WithCaption
SetupCommand => WithCommand
SetupShortCut => WithShortCut
SetupEventOnUpdate => WithEventOnUpdate
SetupEventAfterExecution => WithEventAfterExecution
Inject => WithInjection

Update samples and doc

Update TCommand tests

Update properties in unit Tests.TCommandFactory
in class: TAdvancedCommand = class(TCommand)

  • use base classes TStrings and TStream
  • add isPrime method
  • add Flag injection: ProcessNonPrimeNumbers: boolean

Ignore published properties of TComponent in TClassPropertyList

When

  • getting metadata form TComponent based object with:
  TClassPropertyList.Create(AnyComponentObject);

Then

  • Check TComponent standard published properties:
  • Ignore all standard properties:
  • in Delphi 10.3 there are two such properties:
    1. Name: TComponentName
    2. Tag: NativeInt

Async command event OnProgress

TAsyncCommand = class (TCommand)
    procedure WithEventOnProgress(TProc)
    property ProgressInterval: integer;
    function GetElapsedTime: TTimeSpan;

Add diagnostics to TAsyncCommand:

  • uses System.Diagnostics
  • fStopwatch: TStopwatch;

Property Injector API

variant A

// function InjectProperty(const APropertyName String; Value:Variant): TInjectRec;
Button2.Action := TCommandVclFactory.CreateCommandAction<TButon2Command>(Self,
  'Run command: Button2', [InjectProperty('Memo', Memo1),
  InjectProperty('Edit', Edit1)]);

variant B

// TIjector = class
//    function InjectProperty(APropertyName, Value): TIjector;
Button2.Action := TCommandVclFactory.CreateCommandAction<TButon2Command>(Self,
   'Run command: Button2', TIjector.Create.InjectProperty('Memo', Memo1)
   .InjectProperty('Edit', Edit1));

variant C

Button2.Action := TCommandVclFactory.CreateCommandAction<TButon2Command>(Self,
   'Run command: Button2', ['Memo','Edit'], [Memo1,Edit1]);

variant D

Button2.Action := TCommandVclFactory.CreateCommandAction<TButon2Command>(Self,
  'Run command: Button2', [['property.Memo',Memo1],['Edit',Edit1]]);

DoGuard should be not mandatory to implement

procedure DoGuard; shouldn't be mandatory to implement in TCommand and in TAsyncCommand. Like in sample bellow:

type
  TSamapleCommand
  protected
    procedure DoExecute; override;
  end;

Separate TAsyncCommand and samples

TAsyncCommand unit:

  • Pattern.Command.pas ==> Pattern.AsyncCommand.pas

Extract:

  • TDiceRollCommand and TAsyncDiceRollCommand to separate demo

Refactor project file names

DUnitxCommand.dprTestCommandPattern.dpr
Tests.TCommandFactory.pas ⇒ Tests.TCommand.pas

  • class: TestCommndFactory_BasicCommandTestBasicCommnd
  • class: TestCommndFactory_StrigListCommandTestStrigListCommnd
  • class: TestCommndFactory_AdvancedCommandTestAdvancedCommnd

Add lock to TAsyncCommand.Execute

See TODO in comment:

procedure TAsyncCommand.Execute;
begin
  DoGuard;
  DoPrepare;
  fIsWorking := True;
  TThread.CreateAnonymousThread(
    procedure
    begin
      DoExecute;
      // TODO: lock or critical section is required bellow (critical !!!)
      fIsWorking := True;
    end);
end;

Add More injection unit tests

Requires #5 to be closed

Check:

  1. Expected System.EAssertionFailed exception if no required exection was provided (use TCommandStringList class)
  2. Command with two TStringList published properties (some variants: eg. change injection order)
  3. Command with two TStringList and TComponent published properties between

Async command add WithInjections

function TAsyncCommand.WithInjections(const Injections: array of const): TCommand;
begin
  TComponentInjector.InjectProperties(Self, Injections);
  Result := Self;
end;

Async Command - property ThreadSafeObject

type TAsyncCommand = class(TCommand)
  property ThreadSafeObject: TObject 
    read GetThreadSafeObject
    write SetThreadSafeObject;
function TAsyncCommand GetThreadSafeObject: TObject;
begin
  TMonitor.Enter(Self);
  try
    Result := fThreadSafeObject;
  finally
    TMonitor.Exit(Self);
  end;
end;

Injection inherited class which base class is equal to property class

Allow to inject inherited class, example:

type
  TMyComponent = class(TComponent)
  strict private
    FStrings: TStrings;
  published
    property Strings: TStrings read FStrings write FStrings;
  end;

allow to inject:

  var aComponent := TMyComponent.Create(aOwner);
  var aStringList := TStringList.Create;
  TComponentInjector.InjectProperties(aComponent, [aStringList]);
  Assert (aComponent.Strings = aStringList);

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.